Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 22 additions & 11 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,40 @@
import { useState } from "react";
import { Routes, Route, Navigate } from "react-router";

import AuthInitializer from "@/hooks/AuthListener";
import AuthLayout from "@/layouts/AuthLayout";
import SignInPage from "@/pages/auth/sign-in/SignInPage";
import SignUpPage from "@/pages/auth/sign-up/SignUpPage";
import BootScreen from "@/pages/os/BootScreen";
import OsMain from "@/pages/os/OsMain";
import ProtectedRoute from "@/router/ProtectedRoute";
import PublicRoute from "@/router/PublicRoute";

export default function App() {
const [isBooting, setIsBooting] = useState(false);
const USE_ENTER_MODE = true;
Copy link

Copilot AI Nov 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The USE_ENTER_MODE constant is hard-coded as true without clear documentation of what it controls or why this value was chosen.

Recommendation: Consider one of the following:

  1. Add a descriptive comment explaining what "enter mode" means for the boot screen
  2. Move this to a configuration file or environment variable if it should be configurable
  3. If this is a feature flag, use a more descriptive name like REQUIRE_MANUAL_BOOT or USE_BIOS_MANUAL_MODE
Suggested change
const USE_ENTER_MODE = true;
const [isBooting, setIsBooting] = useState(false);
// If true, the BootScreen will require the user to press "Enter" to continue booting.
// Set to false to allow automatic boot without user interaction.
// This acts as a feature flag for manual boot mode.

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Nov 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The boot screen state is initialized as false, meaning the boot screen will be shown on every app load. However, this doesn't account for the authentication loading state.

When the app first loads:

  1. isBooting is false → BootScreen is shown
  2. Meanwhile, AuthInitializer is running asynchronously
  3. If the user completes the boot screen before auth initializes, they'll see the routes but may experience flashing/redirects as auth state resolves

Recommendation: Consider coordinating the boot screen with authentication initialization, or ensure the boot screen duration is long enough to complete auth hydration. Alternatively, you could show the boot screen only after auth has initialized to prevent redirect flashing.

Copilot uses AI. Check for mistakes.

return (
<>
<AuthInitializer />
<Routes>
<Route element={<PublicRoute />}>
<Route element={<AuthLayout />}>
<Route path="/signin" element={<SignInPage />} />
<Route path="/signup" element={<SignUpPage />} />
{!isBooting ? (
<BootScreen onComplete={() => setIsBooting(true)} useEnterMode={USE_ENTER_MODE} />
) : (
<Routes>
<Route element={<PublicRoute />}>
<Route element={<AuthLayout />}>
<Route path="/signin" element={<SignInPage />} />
<Route path="/signup" element={<SignUpPage />} />
</Route>
</Route>

<Route element={<ProtectedRoute />}>
<Route path="/" element={<OsMain />} />
</Route>
</Route>
<Route element={<ProtectedRoute />}>
<Route path="/" element={<OsMain />} />
</Route>
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>

<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
)}
</>
);
}
Binary file added src/assets/os/bios.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/sounds/windows95-startup-sound.mp3
Binary file not shown.
51 changes: 51 additions & 0 deletions src/pages/os/BootScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { useEffect } from "react";

import Bios from "@/assets/os/bios.png";
import StartupSound from "@/assets/sounds/windows95-startup-sound.mp3";

interface BootScreenProps {
onComplete: () => void;
useEnterMode: boolean;
}

export default function BootScreen({ onComplete, useEnterMode }: BootScreenProps) {
useEffect(() => {
if (!useEnterMode) return;

const handleKeyDown = async (event: KeyboardEvent) => {
if (event.key === "Enter") {
onComplete();

try {
const audio = new Audio(StartupSound);
audio.volume = 0.1;
await audio.play();
} catch (error) {
console.error("오디오 에러:", error);
}
}
};

window.addEventListener("keydown", handleKeyDown);

return () => window.removeEventListener("keydown", handleKeyDown);
}, [useEnterMode, onComplete]);

useEffect(() => {
if (useEnterMode) return;

const timer = setTimeout(() => {
onComplete();
}, 2000);

return () => clearTimeout(timer);
}, [useEnterMode, onComplete]);

return (
<div className="fixed inset-0 flex items-center justify-center bg-black p-4">
<div className="flex h-full w-full flex-col items-center justify-center gap-6">
<img src={Bios} alt="바이오스 화면" className="max-h-[90vh] w-auto object-contain" />
</div>
</div>
);
}
6 changes: 1 addition & 5 deletions src/router/ProtectedRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@ import { Navigate, Outlet } from "react-router";
import { useAuthUser } from "@/hooks/useAuthUser";

export default function ProtectedRoute() {
const { isLoggedIn, isLoading } = useAuthUser();

if (isLoading) {
return <div>Loading...</div>;
}
const { isLoggedIn } = useAuthUser();

Comment on lines +6 to 7
Copy link

Copilot AI Nov 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the isLoading check will cause incorrect redirects during app initialization.

The authentication state starts with isLoading: true and is set to false only after hydrateFromAuth() completes. Without checking isLoading, the route will evaluate isLoggedIn (which is !isLoading && !!user) before authentication is initialized, causing immediate navigation to "/signin" even for authenticated users.

Recommendation: Keep the loading state check to prevent premature redirects:

const { isLoggedIn, isLoading } = useAuthUser();

if (isLoading) {
  return <div>Loading...</div>; // Or a proper loading component
}

if (!isLoggedIn) {
  return <Navigate to="/signin" replace />;
}
Suggested change
const { isLoggedIn } = useAuthUser();
const { isLoggedIn, isLoading } = useAuthUser();
if (isLoading) {
return <div>Loading...</div>;
}

Copilot uses AI. Check for mistakes.
if (!isLoggedIn) {
return <Navigate to="/signin" replace />;
Expand Down
6 changes: 1 addition & 5 deletions src/router/PublicRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@ import { Navigate, Outlet } from "react-router";
import { useAuthUser } from "@/hooks/useAuthUser";

export default function PublicRoute() {
const { isLoggedIn, isLoading } = useAuthUser();

if (isLoading) {
return <div>Loading...</div>;
}
const { isLoggedIn } = useAuthUser();

Comment on lines +6 to 7
Copy link

Copilot AI Nov 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the isLoading check will cause incorrect redirects during app initialization.

The authentication state starts with isLoading: true and is set to false only after hydrateFromAuth() completes. Without checking isLoading, the route will evaluate isLoggedIn (which is !isLoading && !!user) before authentication is initialized, causing immediate navigation to "/" even when the user should be on the signin/signup pages.

Recommendation: Keep the loading state check to prevent premature redirects:

const { isLoggedIn, isLoading } = useAuthUser();

if (isLoading) {
  return <div>Loading...</div>; // Or a proper loading component
}

if (isLoggedIn) {
  return <Navigate to="/" replace />;
}
Suggested change
const { isLoggedIn } = useAuthUser();
const { isLoggedIn, isLoading } = useAuthUser();
if (isLoading) {
return <div>Loading...</div>;
}

Copilot uses AI. Check for mistakes.
if (isLoggedIn) {
return <Navigate to="/" replace />;
Expand Down