Skip to content

Commit 1153088

Browse files
committed
adding loading animation
1 parent 8c1bfd9 commit 1153088

File tree

3 files changed

+72
-29
lines changed

3 files changed

+72
-29
lines changed

src/App.tsx

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ function App() {
4141
const [rootDir, setRootDir] = useState(dummyDir);
4242
const [pdfDataUrl, setPdfDataUrl] = useState<string>();
4343
const [selectedTab, setSelectedTab] = useState<string>();
44+
const [isCompiling, setCompiling] = useState(false);
4445

4546
async function readDirectory({ dirHandle, depth = 0, initialPath = '/', name, parentId }: {
4647
dirHandle: FileSystemDirectoryHandle,
@@ -111,25 +112,32 @@ function App() {
111112
}
112113

113114
async function compileLatex() {
114-
if (!selectedFile?.content) {
115-
return;
116-
}
117-
var pdfTex = new PDFTeX();
118-
pdfTex.initializeFSMethods();
119-
await pdfTex.set_TOTAL_MEMORY(80 * 1024 * 1024);
120-
const binary_pdf = await pdfTex.compileRaw(selectedFile.content);
115+
try {
116+
setCompiling(true);
117+
if (!selectedFile?.content) {
118+
return;
119+
}
120+
var pdfTex = new PDFTeX();
121+
pdfTex.initializeFSMethods();
122+
await pdfTex.set_TOTAL_MEMORY(80 * 1024 * 1024);
123+
const binary_pdf = await pdfTex.compileRaw(selectedFile.content);
121124

122-
if (!binary_pdf) {
123-
return;
124-
}
125+
if (!binary_pdf) {
126+
return;
127+
}
125128

126-
const uint8pdf = binaryStringToUint8Array(binary_pdf);
127-
const blob = new Blob([uint8pdf], { type: "application/pdf" });
128-
const url = URL.createObjectURL(blob);
129+
const uint8pdf = binaryStringToUint8Array(binary_pdf);
130+
const blob = new Blob([uint8pdf], { type: "application/pdf" });
131+
const url = URL.createObjectURL(blob);
129132

130-
setPdfDataUrl(url);
131-
setSelectedTab('pdf');
133+
setPdfDataUrl(url);
134+
setSelectedTab('pdf');
132135

136+
} catch (err) {
137+
console.error(err);
138+
} finally {
139+
setCompiling(false);
140+
}
133141
}
134142

135143
async function newTexFile() {
@@ -157,18 +165,22 @@ function App() {
157165

158166

159167
return (<div>
160-
<HeaderBar items={[{
161-
label: 'New TeX File',
162-
onClick: newTexFile,
163-
}, {
164-
label: 'Open Folder...',
165-
onClick: selectFolder,
166-
disabled: !window.showDirectoryPicker,
167-
}, {
168-
label: 'Compile LaTeX',
169-
onClick: compileLatex,
170-
disabled: !selectedFile || !selectedFile.name.endsWith('.tex')
171-
}]} />
168+
<HeaderBar
169+
items={[{
170+
label: 'New TeX File',
171+
onClick: newTexFile,
172+
}, {
173+
label: 'Open Folder...',
174+
onClick: selectFolder,
175+
disabled: !window.showDirectoryPicker,
176+
}, {
177+
label: 'Compile LaTeX',
178+
onClick: compileLatex,
179+
disabled: !selectedFile || !selectedFile.name.endsWith('.tex'),
180+
compileButton: true,
181+
}]}
182+
isCompiling={isCompiling}
183+
/>
172184
<div style={{
173185
display: 'flex',
174186
}}>

src/components/header-bar.tsx

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
import { useState, type CSSProperties } from "react";
2+
import { getIcon } from "./icon";
23

34
interface Item {
45
label: string,
56
onClick: () => void;
67
disabled?: boolean;
8+
compileButton?: boolean;
79
}
810

9-
function Button(params: { item: Item; }) {
11+
function Button(params: { item: Item; isCompiling: boolean; }) {
1012
const buttonStyle: CSSProperties = {
1113
backgroundColor: 'transparent',
1214
color: params.item.disabled ? '#aaaaaa' : '#ffffff',
1315
borderWidth: 0,
1416
cursor: !params.item.disabled ? 'pointer' : undefined,
17+
flexDirection: 'row',
18+
display: 'flex',
19+
alignItems: 'center',
20+
gap: 4
1521
};
1622

1723
const [isHovered, setHovered] = useState(false);
@@ -25,12 +31,34 @@ function Button(params: { item: Item; }) {
2531
onMouseEnter={() => setHovered(true)}
2632
onMouseLeave={() => setHovered(false)}
2733
>
34+
{(() => {
35+
if (!params.item.compileButton) {
36+
return <></>;
37+
}
38+
return <>
39+
<style>{`
40+
@keyframes spin {
41+
from { transform: rotate(0deg); }
42+
to { transform: rotate(360deg); }
43+
}
44+
`}</style>
45+
46+
<span style={{
47+
display: "flex",
48+
animation: params.isCompiling ? "spin 1s linear infinite" : undefined,
49+
}}>
50+
{getIcon('', params.isCompiling ? 'loading' : 'play')}
51+
</span>
52+
</>;
53+
54+
})()}
2855
{params.item.label}
2956
</button>;
3057
}
3158

3259
export default function HeaderBar(params: {
3360
items: Item[];
61+
isCompiling: boolean;
3462
}) {
3563

3664
return <div style={{
@@ -43,7 +71,7 @@ export default function HeaderBar(params: {
4371
backgroundColor: '#333333',
4472
}}>
4573
{params.items.map((item) => {
46-
return <Button key={item.label} item={item} />;
74+
return <Button key={item.label} item={item} isCompiling={params.isCompiling} />;
4775
})}
4876
</div>;
4977
}

src/components/icon.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
} from "react-icons/si";
1010
import { FcFolder, FcOpenedFolder, FcPicture, FcFile } from "react-icons/fc";
1111
import { AiFillFileText } from "react-icons/ai";
12+
import { FaPlay, FaSpinner } from "react-icons/fa";
1213

1314
function getIconHelper() {
1415
const cache = new Map<string, ReactNode>();
@@ -26,6 +27,8 @@ function getIconHelper() {
2627
cache.set("txt", <AiFillFileText color="white" />);
2728
cache.set("closedDirectory", <FcFolder />);
2829
cache.set("openDirectory", <FcOpenedFolder />);
30+
cache.set("loading", <FaSpinner />);
31+
cache.set("play", <FaPlay size={10} />);
2932
return function (extension: string, name: string): ReactNode {
3033
if (cache.has(extension)) return cache.get(extension);
3134
else if (cache.has(name)) return cache.get(name);

0 commit comments

Comments
 (0)