FIX: Spinner for the editor content.

This commit is contained in:
Hayden Hargreaves 2025-03-06 18:53:33 -07:00
parent 9ec4976b31
commit cf886b8983
4 changed files with 42 additions and 14 deletions

View File

@ -31,7 +31,7 @@ try {
/**
* Invalid file extensions for the file editor.
*/
const INVALID_EXTS: string[] = ["exe", "dll", "obj", "lib", "bin", "dat", "pdf", "jpg", "jpeg", "png", "gif", "webm", "webp", "bmp", "mp3", "wav", "mp4", "avi", "zip", "rar", "7z", "iso", "dmg", "class", "pyc", "o", "a", "woff", "woff2", "ttf", "otf", "db", "sqlite", "mdb", "accdb", "psd", "ai", "indd", "blend", "fbx", "unitypackage", "pak", "sav", "msi", ".doc", ".docx", ".dot", ".dotx", ".docm", ".dotm", ".rtf", ".txt", ".xls", ".xlsx", ".xlsm", ".xltx", ".xltm", ".csv", ".ppt", ".pptx", ".pptm", ".potx", ".potm", ".ppsx", ".ppsm", ".mdb", ".accdb", ".accde", ".accdt", ".pst", ".ost", ".msg", ".one", ".onetoc2", ".pub", ".vsd", ".vsdx", ".vssx", ".vstx", ".odc", ".oft", ".pki"];
const INVALID_EXTS: string[] = ["exe", "dll", "obj", "lib", "bin", "dat", "pdf", "jpg", "jpeg", "png", "gif", "webm", "webp", "bmp", "mp3", "wav", "mp4", "avi", "zip", "rar", "7z", "iso", "dmg", "class", "pyc", "o", "a", "woff", "woff2", "ttf", "otf", "db", "sqlite", "mdb", "accdb", "psd", "ai", "indd", "blend", "fbx", "unitypackage", "pak", "sav", "msi", "doc", "docx", "dot", "dotx", "docm", "dotm", "rtf", "txt", "xls", "xlsx", "xlsm", "xltx", "xltm", "csv", "ppt", "pptx", "pptm", "potx", "potm", "ppsx", "ppsm", "mdb", "accdb", "accde", "accdt", "pst", "ost", "msg", "one", "onetoc2", "pub", "vsd", "vsdx", "vssx", "vstx", "odc", "oft", "pki", "odg"];
/**
* Configure cors, this should work for both production and development.

View File

@ -0,0 +1,20 @@
import "../index.css"
/**
* Simple loading spinner for the text editor.
* @returns {JSX.Element}
* @constructor
*/
export default function ContentLoading() {
return (
<div className="h-9/10 w-full flex flex-col items-center justify-center">
<div className="flex">
<div
className="animate-spin rounded-full border-blue-500 border-3 border-t-transparent size-6 mr-2 ">
</div>
<p className="text-lg text-black opacity-90">Content loading...</p>
</div>
<p className="text-xs text-gray-500 my-2">For large files, this may take a while.</p>
</div>
);
};

View File

@ -1,6 +1,7 @@
import {useEffect, useRef, useState} from "react";
import ContentLoading from "./ContentLoading.jsx";
export default function Editor({content, path, exit, saveExit}) {
export default function Editor({content, path, exit, saveExit, loading}) {
const [text, setText] = useState("");
/**
* Store a reference to the text area object
@ -54,14 +55,17 @@ export default function Editor({content, path, exit, saveExit}) {
<div className="relative z-10 bg-white p-8 rounded-lg shadow-lg w-3/4 h-5/6 border-1 border-gray-400">
<h2 className="text-lg font-semibold mb-4 text-blue-400">Editing File: <span
className="font-mono text-black bg-gray-300 p-1 rounded-md">{path}</span></h2>
<textarea
onKeyDown={handleKeyPress}
tabIndex={-1}
ref={textareaRef}
onInput={updateText}
value={text}
className="border-1 border-gray-300 rounded-md w-full h-9/10 p-1 resize-none text-sm font-mono">
{loading && <ContentLoading/>}
{loading ||
<textarea
onKeyDown={handleKeyPress}
tabIndex={-1}
ref={textareaRef}
onInput={updateText}
value={text}
className="border-1 border-gray-300 rounded-md w-full h-9/10 p-1 resize-none text-sm font-mono">
</textarea>
}
<div className="flex justify-end">
<button
title="Exit without saving"

View File

@ -30,6 +30,7 @@ export default function Dashboard() {
const [editing, setEditing] = useState("");
const [childrenLoading, setChildrenLoading] = useState(false);
const [downloadLoading, setDownloadLoading] = useState(false);
const [contentLoading, setContentLoading] = useState(false);
const navigate = useNavigate();
@ -232,10 +233,9 @@ export default function Dashboard() {
// Send request to server to update the file. This will return nothing
// so no need for any promise handling.
updateContent(editing, newContent);
// Set editing back to nothing to hide the modal
setEditing("");
updateContent(editing, newContent).finally(() => {
setEditing("");
});
};
@ -259,6 +259,7 @@ export default function Dashboard() {
return await resp.json();
};
setContentLoading(true);
// Prevent running when nothing is being edited. Also prevents a call on mount.
if (editing) {
// Fetch the data and handle errors accordingly
@ -270,6 +271,8 @@ export default function Dashboard() {
setEditing("");
setError(data.error);
}
}).finally(() => {
setContentLoading(false)
});
}
@ -287,7 +290,8 @@ export default function Dashboard() {
{error && <Error error={error} clear={clearError}/>}
{(editing !== "" && !error) &&
<Editor content={editingFileContent} path={editing} exit={exitFile} saveExit={exitAndSaveFile}/>}
<Editor content={editingFileContent} path={editing} exit={exitFile} saveExit={exitAndSaveFile}
loading={contentLoading}/>}
<PathDisplay path={path} updatePath={updatePath} backHome={backHome} backArrow={backArrow}
enabled={path.length > defaultPath.length}/>