Skip to content

Commit ca1000b

Browse files
authored
Merge pull request #13 from IgorD-lab/feat/text-viewer AI slop PR
feat: implemente text viewing funcitonality for portfolio/file-explorer
2 parents 804412f + d5f8b93 commit ca1000b

File tree

7 files changed

+90
-44
lines changed

7 files changed

+90
-44
lines changed

src/App.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import gsap from 'gsap';
22
import { Draggable } from 'gsap/Draggable';
33

44
import { Navbar, Welcome, Dock } from '#components';
5-
import { Terminal, Safari, Resume, Finder } from '#windows';
5+
import { Terminal, Safari, Resume, Finder, Text } from '#windows';
66

77
gsap.registerPlugin(Draggable);
88

@@ -17,6 +17,7 @@ const App = () => {
1717
<Safari />
1818
<Resume />
1919
<Finder />
20+
<Text />
2021
</main>
2122
);
2223
};

src/components/Dock.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import { gsap } from 'gsap';
44

55
import { DOCK_APPS } from '#constants';
66
import { useGSAP } from '@gsap/react';
7-
import useWindowStore, { WindowKey } from '#store/window';
7+
import { WindowID } from '#types';
8+
import useWindowStore from '#store/window';
89

910
interface AppToggleProps {
1011
id: string;
@@ -67,7 +68,7 @@ const Dock = () => {
6768
const toggleApp = (app: AppToggleProps) => {
6869
if (!app.canOpen) return;
6970

70-
const windowId = app.id as WindowKey;
71+
const windowId = app.id as WindowID;
7172
const window = windows[windowId];
7273

7374
if (!window) {

src/hoc/WindowWrapper.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import React, {
55
useLayoutEffect,
66
} from 'react';
77
// We use 'import type' to ensure these are erased at runtime
8-
import type { WindowKey } from '#store/window';
8+
import type { WindowID } from '#types';
99
import useWindowStore from '#store/window';
1010
import { useGSAP } from '@gsap/react';
1111
import gsap from 'gsap';
@@ -19,7 +19,7 @@ import { Draggable } from 'gsap/Draggable';
1919
*/
2020
const WindowWrapper = <P extends object>(
2121
Component: ComponentType<P>,
22-
windowKey: WindowKey,
22+
windowKey: WindowID,
2323
): ((props: P) => ReactElement | null) => {
2424
// This is the actual component that gets rendered
2525
const Wrapped = (props: P) => {

src/store/window.ts

Lines changed: 19 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,54 @@
11
import { create } from 'zustand';
22
import { immer } from 'zustand/middleware/immer';
33
import { INITIAL_Z_INDEX, WINDOW_CONFIG } from '#constants';
4-
5-
/** * 1. THE BLUEPRINTS (Interfaces)
6-
* Think of these as the "Rules of the House."
7-
* They tell TypeScript exactly what a Window looks like.
8-
*/
9-
interface WindowState {
10-
isOpen: boolean;
11-
zIndex: number;
12-
data: unknown; // Changed from null to any/unknown so it can actually hold data
13-
}
14-
15-
// WindowKey creates a list of allowed names (e.g., 'terminal' | 'browser')
16-
// based on your actual config file (constants/index.ts).
17-
export type WindowKey = keyof typeof WINDOW_CONFIG;
4+
import { WindowID, WindowState, FinderItem } from '#types';
185

196
interface WindowStore {
20-
windows: Record<WindowKey, WindowState>; // A map of all windows
21-
nextZIndex: number; // The "depth" for the next focused window
22-
openWindow: (windowKey: WindowKey, data?: unknown) => void;
23-
closeWindow: (windowKey: WindowKey) => void;
24-
focusWindow: (windowKey: WindowKey) => void;
7+
windows: Record<WindowID, WindowState>;
8+
nextZIndex: number;
9+
openWindow: (windowKey: WindowID, data?: FinderItem) => void;
10+
closeWindow: (windowKey: WindowID) => void;
11+
focusWindow: (windowKey: WindowID) => void;
2512
}
2613

27-
/**
28-
* 2. THE STORE
29-
* We use 'immer' middleware here. Normally, React state must be "immutable"
30-
* (you can't change it, you have to replace it).
31-
* Immer lets us write 'state.windows[key].isOpen = true' which is much easier to read!
32-
*/
3314
const useWindowStore = create<WindowStore>()(
3415
immer((set) => ({
35-
// Initial Data
36-
windows: WINDOW_CONFIG,
16+
// Initialize using the config from constants
17+
windows: WINDOW_CONFIG as Record<WindowID, WindowState>,
3718
nextZIndex: INITIAL_Z_INDEX + 1,
3819

39-
// ACTION: Open a window
40-
openWindow: (windowKey, data = null) =>
20+
// Open a specific window and optionally pass file data (FinderItem)
21+
openWindow: (windowKey, data) =>
4122
set((state) => {
4223
const win = state.windows[windowKey];
4324
if (!win) return;
4425

4526
win.isOpen = true;
46-
win.zIndex = state.nextZIndex; // Put it on top
47-
win.data = data ?? win.data; // Attach any extra info (like a file path)
48-
state.nextZIndex++; // Prepare the next Z-Index for the next window
27+
win.zIndex = state.nextZIndex;
28+
// Save the file object (Nike Project.txt, etc) into the window's data slot
29+
if (data) {
30+
state.windows[windowKey].data = data as FinderItem;
31+
}
32+
state.nextZIndex++;
4933
}),
5034

51-
// ACTION: Hide a window
35+
// Close window and wipe its local data to keep it clean for next use
5236
closeWindow: (windowKey) =>
5337
set((state) => {
5438
const win = state.windows[windowKey];
5539
if (!win) return;
5640

5741
win.isOpen = false;
58-
win.zIndex = INITIAL_Z_INDEX; // Send it back to the bottom
42+
win.zIndex = INITIAL_Z_INDEX;
5943
win.data = null;
6044
}),
6145

62-
// ACTION: Click to focus
46+
// Bring window to front
6347
focusWindow: (windowKey) =>
6448
set((state) => {
6549
const win = state.windows[windowKey];
6650
if (!win) return;
6751

68-
// Every time you click, we give it a higher number than anyone else
6952
win.zIndex = state.nextZIndex;
7053
state.nextZIndex++;
7154
}),

src/types/index.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// TODO: move all types here
21
export type WindowID =
32
| 'finder'
43
| 'contact'
@@ -14,10 +13,24 @@ export interface FinderItem {
1413
name: string;
1514
icon: string;
1615
kind: 'folder' | 'file';
16+
// Common properties
1717
type?: string;
1818
fileType?: string;
1919
position?: string;
20-
imageUrl?: string;
20+
windowPosition?: string;
21+
// File specific properties
2122
href?: string;
23+
imageUrl?: string;
24+
// Text file specific (Flat, not nested)
25+
image?: string;
26+
subtitle?: string;
27+
description?: string[];
28+
// Folders
2229
children?: FinderItem[];
2330
}
31+
32+
export interface WindowState {
33+
isOpen: boolean;
34+
zIndex: number;
35+
data: FinderItem | null;
36+
}

src/windows/Text.tsx

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { WindowControls } from '#components';
2+
import WindowWrapper from '#hoc/WindowWrapper';
3+
import useWindowStore from '#store/window';
4+
import { FinderItem } from '#types';
5+
6+
const Text = () => {
7+
const { windows } = useWindowStore();
8+
9+
// Directly access the data stored for this window
10+
const data = windows.txtfile?.data as FinderItem | undefined;
11+
12+
if (!data) return null;
13+
14+
// These properties exist directly on FinderItem based on your constants
15+
const { name, image, subtitle, description } = data;
16+
17+
return (
18+
<>
19+
<div id="window-header">
20+
<WindowControls target="txtfile" />
21+
<h2>{name}</h2>
22+
</div>
23+
<div className="p-5 space-y-6 bg-white">
24+
{image ? (
25+
<div className="w-full">
26+
<img src={image} alt={name} className="w-full h-auto rounded" />
27+
</div>
28+
) : null}
29+
30+
{subtitle ? (
31+
<h3 className="text-lg font-semibold">{subtitle}</h3>
32+
) : null}
33+
34+
{Array.isArray(description) && description.length > 0 ? (
35+
<div className="space-y-3 leading-relaxed text-base text-gray-800">
36+
{description.map((para, idx) => (
37+
<p key={idx}>{para}</p>
38+
))}
39+
</div>
40+
) : null}
41+
</div>
42+
</>
43+
);
44+
};
45+
46+
const TextWindow = WindowWrapper(Text, 'txtfile');
47+
export default TextWindow;

src/windows/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ import Terminal from '#windows/Terminal';
22
import Safari from '#windows/Safari';
33
import Resume from '#windows/Resume';
44
import Finder from '#windows/Finder';
5+
import Text from '#windows/Text';
56

6-
export { Terminal, Safari, Resume, Finder };
7+
export { Terminal, Safari, Resume, Finder, Text };

0 commit comments

Comments
 (0)