Skip to content

Commit d2c02c3

Browse files
committed
adding pdf view
1 parent c66f3ed commit d2c02c3

File tree

5 files changed

+129
-8
lines changed

5 files changed

+129
-8
lines changed

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
v22.12.0

src/App.tsx

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { FileTree } from './components/file-tree';
66
import Sidebar from './components/sidebar';
77
import HeaderBar from './components/header-bar';
88
import { PDFTeX } from './pdftex/pdftex';
9+
import Tabs from './components/tabs';
910

1011
const dummyDir: Directory = {
1112
id: "1",
@@ -17,10 +18,29 @@ const dummyDir: Directory = {
1718
files: []
1819
};
1920

21+
function PDFViewer({ dataUrl }: { dataUrl?: string; }) {
22+
return (
23+
<>
24+
{dataUrl &&
25+
<iframe
26+
src={dataUrl}
27+
style={{
28+
width: "100%",
29+
height: "100%",
30+
border: "none",
31+
}}
32+
title="PDF preview"
33+
/>
34+
}
35+
</>
36+
);
37+
}
38+
2039
function App() {
2140
const [selectedFile, setSelectedFile] = useState<File | undefined>(undefined);
2241
const [rootDir, setRootDir] = useState(dummyDir);
23-
42+
const [pdfDataUrl, setPdfDataUrl] = useState<string>();
43+
const [selectedTab, setSelectedTab] = useState<string>();
2444

2545
async function readDirectory({ dirHandle, depth = 0, initialPath = '/', name, parentId }: {
2646
dirHandle: FileSystemDirectoryHandle,
@@ -106,7 +126,9 @@ function App() {
106126
const uint8pdf = binaryStringToUint8Array(binary_pdf);
107127
const blob = new Blob([uint8pdf], { type: "application/pdf" });
108128
const url = URL.createObjectURL(blob);
109-
window.open(url, "_blank");
129+
130+
setPdfDataUrl(url);
131+
setSelectedTab('pdf');
110132

111133
}
112134

@@ -157,9 +179,36 @@ function App() {
157179
onSelect={setSelectedFile}
158180
/>
159181
</Sidebar>
160-
<Code
161-
selectedFile={selectedFile}
162-
/>
182+
<div style={{
183+
display: 'flex',
184+
flex: 1,
185+
height: window.innerHeight - 25
186+
}}>
187+
<Tabs
188+
tabs={[{
189+
key: 'code',
190+
label: selectedFile?.name || 'code',
191+
}, {
192+
key: 'pdf',
193+
label: 'pdf'
194+
}]}
195+
selectedTab={selectedTab}
196+
setSelectedTab={setSelectedTab}
197+
>
198+
{({ selectedTab }) => {
199+
if (selectedTab === 'code') {
200+
return <Code
201+
selectedFile={selectedFile}
202+
/>;
203+
}
204+
if (selectedTab === 'pdf') {
205+
return <PDFViewer
206+
dataUrl={pdfDataUrl}
207+
/>;
208+
}
209+
}}
210+
</Tabs>
211+
</div>
163212
</div>
164213
</div>
165214
);

src/components/sidebar.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ export const Sidebar = ({ children }: { children: ReactNode; }) => {
55
<aside style={{
66
display: 'block',
77
width: 250,
8-
// height: '100vh',
98
borderRightStyle: 'solid',
109
borderRightWidth: 2,
1110
borderColor: '#242424',

src/components/tabs.tsx

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { useEffect, useState, type CSSProperties } from "react";
2+
3+
interface TabInfo {
4+
key: string;
5+
label: string;
6+
}
7+
8+
function Button(params: { item: TabInfo; setSelectedTab: (value: string) => void; selectedTab: string; }) {
9+
const buttonStyle: CSSProperties = {
10+
color: '#ffffff',
11+
borderWidth: 0,
12+
cursor: 'pointer',
13+
minWidth: 120,
14+
};
15+
16+
const [isHovered, setHovered] = useState(false);
17+
18+
return <button
19+
style={{
20+
...buttonStyle,
21+
backgroundColor: isHovered || params.item.key === params.selectedTab ? '#222222' : '#343434',
22+
}}
23+
onClick={() => params.setSelectedTab(params.item.key)}
24+
onMouseEnter={() => setHovered(true)}
25+
onMouseLeave={() => setHovered(false)}
26+
>
27+
{params.item.label}
28+
</button>;
29+
}
30+
31+
export default function Tabs(params: {
32+
tabs: TabInfo[];
33+
children: ({ selectedTab }: { selectedTab: string; }) => React.ReactNode | undefined;
34+
selectedTab?: string;
35+
setSelectedTab?: (value: string) => void;
36+
}) {
37+
const [selectedTab, setSelectedTab] = useState(params.tabs[0].key);
38+
39+
useEffect(() => {
40+
if (params.selectedTab && params.selectedTab !== selectedTab) {
41+
setSelectedTab(params.selectedTab);
42+
}
43+
}, [params.selectedTab]);
44+
45+
46+
useEffect(() => {
47+
if (params.setSelectedTab) {
48+
params.setSelectedTab(selectedTab);
49+
}
50+
}, [selectedTab]);
51+
52+
return <div style={{
53+
width: '100%',
54+
flex: 1,
55+
display: 'flex',
56+
flexDirection: 'column',
57+
}}>
58+
<div style={{
59+
width: '100%',
60+
height: 30,
61+
display: 'flex',
62+
borderColor: '#242424',
63+
flexDirection: 'row',
64+
gap: 2,
65+
}}>
66+
{params.tabs.map((tab) => {
67+
return <Button key={tab.label} item={tab} setSelectedTab={setSelectedTab} selectedTab={selectedTab} />;
68+
})}
69+
</div>
70+
{params.children({ selectedTab })}
71+
72+
</div>;
73+
}

src/editor/code.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,7 @@ export default function Code({ selectedFile }: { selectedFile: File | undefined;
7777

7878
return (
7979
<div style={{
80-
width: 'calc(100% - 250px)',
81-
height: window.innerHeight - 25,
80+
flex: 1,
8281
margin: 0,
8382
fontSize: 16,
8483
}}>

0 commit comments

Comments
 (0)