From 9471a1338836046092e198ceaa6b1ffeaeaaf7ac Mon Sep 17 00:00:00 2001 From: nomi-nonsz Date: Wed, 3 Sep 2025 12:09:00 +0700 Subject: [PATCH] working window manager --- src/app/page.tsx | 53 ++++++++++--------- src/components/client-windows.tsx | 86 ++++++++++++++++++++++++++----- src/components/floating-label.tsx | 8 ++- src/components/windows.tsx | 36 +++++-------- src/hooks/window-manager.tsx | 83 +++++++++++++++++++++++++++-- 5 files changed, 196 insertions(+), 70 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index 3dbee5c..c8cf4c0 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -6,35 +6,38 @@ import HomeText from "@/components/home-text.mdx" import Link from "next/link"; import { FakeWindow, HomeWindows } from "@/components/windows"; import Taskbar from "@/components/taskbar"; +import { WindowManagerProvider } from "@/hooks/window-manager"; export default function Home() { return (<>
- - -
-

- Nonszy Workspace -

-
- - - -
- -
-
-

⚡ Powered with Cloudflare ☁️

-
-
-

© 2025 Nomi Nonszy

-

- Terms and Privacy -

-
-
+ + + +
+

+ Nonszy Workspace +

+
+ + + +
+ +
+
+

⚡ Powered with Cloudflare ☁️

+
+
+

© 2025 Nomi Nonszy

+

+ Terms and Privacy +

+
+
+
); } diff --git a/src/components/client-windows.tsx b/src/components/client-windows.tsx index 174ab8a..b51c226 100644 --- a/src/components/client-windows.tsx +++ b/src/components/client-windows.tsx @@ -1,8 +1,23 @@ 'use client' +import { FakeWindow, useWindowManager } from "@/hooks/window-manager"; import { Icon } from "@iconify/react"; import clsx from "clsx"; -import { useState, useRef, useEffect } from "react"; +import React, { useState, useRef, useEffect, useReducer } from "react"; + +export const RestoreWindowsButton = ({ onClick, className, ...props}: React.ComponentProps<"button">) => { + const windowManager = useWindowManager(); + + const isAnyWindowsClosed = !windowManager.windows.find(w => w.closed == true); + + return ( + - + + -
+
{children}
diff --git a/src/components/floating-label.tsx b/src/components/floating-label.tsx index 9a3203d..85a1ee6 100644 --- a/src/components/floating-label.tsx +++ b/src/components/floating-label.tsx @@ -8,10 +8,8 @@ export const FloatingLabel = ({ children: React.ReactNode; }) => { return ( -
- - {children} - -
+ + {children} + ); }; \ No newline at end of file diff --git a/src/components/windows.tsx b/src/components/windows.tsx index 8512dc0..7ca3149 100644 --- a/src/components/windows.tsx +++ b/src/components/windows.tsx @@ -1,6 +1,6 @@ import { Icon } from "@iconify/react"; import { FloatingLabel } from "@/components/floating-label"; -import { FakeRelativeWindow } from "./client-windows"; +import { FakeRelativeWindow, RestoreWindowsButton } from "./client-windows"; import Image from "next/image" import Link from "next/link"; @@ -16,12 +16,17 @@ export const FakeWindow = ({
{windowText}
- -
- - -
-
+
+ + Restore Windows + + +
+ + +
+
+
@@ -34,23 +39,6 @@ export const FakeWindow = ({ export const HomeWindows = () => (
- {/* -
- Left 4 Dead -

Join my Left 4 Dead 2 server!

-
-
*/} FakeWindow | undefined; + add: (window: FakeWindow) => void; + updateWindow: (name: string, changes: Partial) => void; + toggleMinimize: (name: string) => void; + close: (name: string) => void; + remove: (name: string) => void; + move: (name: string, offset: { x: number; y: number }) => void; + openAll: () => void; +} + +const WindowManagerContext = createContext(undefined); + +export const WindowManagerProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { + const [windows, setWindows] = useState([]); + const [isInit, setInit] = useState(false); + const [isLocalDataExists, setExists] = useState(false); + + useEffect(() => { + const data = localStorage.getItem("fake-windows-data"); + if (data) { + setWindows(JSON.parse(data)); + setExists(true); + } + setInit(true); + }, []); + + useEffect(() => { + if (isInit && typeof window !== 'undefined' && windows.length > 0) { + window.localStorage.setItem('fake-windows-data', JSON.stringify(windows)); + } + }, [windows]); + + const get = (name: string) => windows.find(window => window.name == name); + const add = (window: FakeWindow) => setWindows(w => [...w, window]); + const updateWindow = (name: string, changes: Partial) => + setWindows(w => + w.map(win => win.name === name ? { ...win, ...changes } : win) + ); + const toggleMinimize = (name: string) => + setWindows(w => + w.map(win => win.name === name ? { ...win, minimized: !win.minimized } : win) + ); + const open = (name: string) => updateWindow(name, { closed: false }); + const close = (name: string) => updateWindow(name, { closed: true }); + const move = (name: string, offset: { x: number; y: number }) => + updateWindow(name, { offset }); + + const remove = (name: string) => setWindows(w => w.filter(win => win.name !== name)); + + const openAll = () => setWindows(w => + w.map(win => ({ ...win, closed: false })) + ); + + return ( + + {children} + + ); +}; + +export function useWindowManager() { + const ctx = useContext(WindowManagerContext); + if (!ctx) throw new Error("useWindowManager must be used within WindowManagerProvider"); + return ctx; } \ No newline at end of file