Skip to content

Commit 82fb5ba

Browse files
committed
TL Client frame WIP
1 parent e515476 commit 82fb5ba

File tree

7 files changed

+145
-4
lines changed

7 files changed

+145
-4
lines changed

packages/react/src/components/layout/Frame.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ export function LocationAwareReactivity() {
6161
const isFullscreen =
6262
location.pathname.startsWith("/watch") ||
6363
location.pathname.startsWith("/edit") ||
64-
location.pathname.startsWith("/scripteditor");
64+
location.pathname.startsWith("/scripteditor") ||
65+
location.pathname.startsWith("/tlclient");
6566

6667
indicatePageFullscreen(isFullscreen);
6768
}, [location.pathname, indicatePageFullscreen]);

packages/react/src/components/tldex/new-editor/frame.tsx packages/react/src/components/tldex/new-editor/TLEditorFrame.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useCallback, useEffect, useState } from "react";
2-
import "./frame.css";
2+
import "./TLEditorFrame.css";
33
import { useBeforeUnload, useNavigate } from "react-router-dom";
44
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
55
import { PlayerWrapper } from "@/components/layout/PlayerWrapper";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import React, { useState, useEffect } from "react";
2+
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
3+
import { PlayerWrapper } from "@/components/layout/PlayerWrapper";
4+
import { useSetAtom } from "jotai";
5+
import { headerHiddenAtom } from "@/hooks/useFrame";
6+
import { Button } from "@/shadcn/ui/button";
7+
import { Input } from "@/shadcn/ui/input";
8+
import { idToVideoURL } from "@/lib/utils";
9+
10+
const TLControlBar = ({
11+
videoId,
12+
onVideoIdChange,
13+
onLoad,
14+
}: {
15+
videoId: string;
16+
onVideoIdChange: (videoId: string) => void;
17+
onLoad: () => void;
18+
}) => (
19+
<div className="flex gap-2 rounded-lg bg-base-3 p-2">
20+
<Input
21+
value={videoId}
22+
onChange={(e) => onVideoIdChange(e.target.value)}
23+
placeholder="Enter video ID..."
24+
className="w-64"
25+
/>
26+
<Button onClick={onLoad}>Load</Button>
27+
</div>
28+
);
29+
30+
export default function TLClientFrame() {
31+
const [videoId, setVideoId] = useState("");
32+
const makeHeaderHide = useSetAtom(headerHiddenAtom);
33+
const [speakers, setSpeakers] = useState([
34+
{ id: 1, name: "Speaker 1" },
35+
{ id: 2, name: "Speaker 2" },
36+
{ id: 3, name: "Speaker 3" },
37+
{ id: 4, name: "Speaker 4" },
38+
{ id: 5, name: "Speaker 5" },
39+
{ id: 6, name: "Speaker 5" },
40+
{ id: 7, name: "Speaker 5" },
41+
{ id: 8, name: "Speaker 5" },
42+
{ id: 9, name: "Speaker 5" },
43+
{ id: 10, name: "Speaker 5" },
44+
]);
45+
const [currentSpeaker, setCurrentSpeaker] = useState(1);
46+
const [currentInput, setCurrentInput] = useState("");
47+
48+
useEffect(() => {
49+
makeHeaderHide(true);
50+
return () => makeHeaderHide(false);
51+
}, [makeHeaderHide]);
52+
53+
return (
54+
<div className="flex h-screen w-screen flex-col gap-2 bg-base-2 p-2">
55+
<TLControlBar
56+
videoId={videoId}
57+
onVideoIdChange={setVideoId}
58+
onLoad={() => {
59+
/* Implement load logic */
60+
}}
61+
/>
62+
63+
<div className="flex flex-1 flex-col gap-2">
64+
{/* Main viewing area with 23:9 aspect ratio constraint */}
65+
<div className="relative w-full" style={{ paddingTop: "39.13%" }}>
66+
<div className="absolute inset-0">
67+
<PanelGroup
68+
direction="horizontal"
69+
className="h-full rounded-lg bg-base-3"
70+
>
71+
<Panel minSize={13} defaultSize={15}>
72+
<div className="flex h-full flex-col border-r border-base-4">
73+
<div className="border-b border-base-4 p-2 text-sm font-medium">
74+
YouTube Chat
75+
</div>
76+
<div className="flex-1 overflow-y-auto p-2">
77+
{/* Chat content */}
78+
</div>
79+
</div>
80+
</Panel>
81+
<PanelResizeHandle className="w-2 bg-base-2 hover:bg-base-4" />
82+
<Panel minSize={30} defaultSize={70}>
83+
<div className="flex h-full flex-col items-center justify-center">
84+
<div className="aspect-video w-full">
85+
<PlayerWrapper id={videoId} url={idToVideoURL(videoId)} />
86+
</div>
87+
</div>
88+
</Panel>
89+
<PanelResizeHandle className="w-2 bg-base-2 hover:bg-base-4" />
90+
<Panel minSize={13} defaultSize={15}>
91+
<div className="flex h-full flex-col border-l border-base-4">
92+
<div className="border-b border-base-4 p-2 text-sm font-medium">
93+
TL Chat
94+
</div>
95+
<div className="flex-1 overflow-y-auto p-2">
96+
{/* TL chat content */}
97+
</div>
98+
</div>
99+
</Panel>
100+
</PanelGroup>
101+
</div>
102+
</div>
103+
104+
{/* Input and speaker selection area */}
105+
<div className="container flex flex-col gap-2 rounded-lg bg-base-3 p-2">
106+
<Input
107+
value={currentInput}
108+
onChange={(e) => setCurrentInput(e.target.value)}
109+
placeholder="Enter translation..."
110+
className="h-12 text-lg"
111+
/>
112+
113+
<div className="grid grid-cols-10 gap-2">
114+
{speakers.map((speaker, i) => (
115+
<Button
116+
key={i}
117+
variant={
118+
currentSpeaker === speaker.id ? "primary" : "base-outline"
119+
}
120+
className="h-10 justify-start gap-2"
121+
onClick={() => setCurrentSpeaker(speaker.id)}
122+
>
123+
<span className="text-xs text-base-11">{(i + 1) % 10}</span>
124+
<span className="truncate">{speaker.name}</span>
125+
</Button>
126+
))}
127+
</div>
128+
</div>
129+
</div>
130+
</div>
131+
);
132+
}

packages/react/src/routes/router.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ const Login = lazy(() =>
9292
const TLEditorPage = lazy(() =>
9393
import("./tleditor").then((module) => ({ default: module.TLEditorPage })),
9494
);
95+
const TLClientPage = lazy(() =>
96+
import("./tlclient").then((module) => ({ default: module.TLClientPage })),
97+
);
9598
const Watch = lazy(() =>
9699
import("./watch").then((module) => ({ default: module.Watch })),
97100
);
@@ -166,7 +169,7 @@ export const routes = (
166169
<Route path="multiview" Component={Multiview} />
167170
<Route path="kitchensink" Component={Kitchensink} />
168171
<Route path="login" Component={Login} />
169-
<Route path="tlclient" element={<div>Translation Client</div>} />
172+
<Route path="tlclient" Component={TLClientPage} />
170173
<Route path="scripteditor" Component={TLEditorPage} />
171174
<Route path="watch/:id" Component={Watch} />
172175
<Route path="debug" Component={ResetClientPage} />
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import TLClientFrame from "@/components/tldex/tl-client/TLClientFrame";
2+
3+
export function TLClientPage() {
4+
return <TLClientFrame />;
5+
}
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { TLEditorFrame } from "@/components/tldex/new-editor/frame";
1+
import { TLEditorFrame } from "@/components/tldex/new-editor/TLEditorFrame";
22
export function TLEditorPage() {
33
return <TLEditorFrame />;
44
}

0 commit comments

Comments
 (0)