Files UX Sprint (#3019)

* chore: dedupe lockfile

Signed-off-by: Evan Song <theevansong@gmail.com>

* fix: incorrect spacing between editing and browsing state

Signed-off-by: Evan Song <theevansong@gmail.com>

* chore: improve files image viewer toolbar

Signed-off-by: Evan Song <theevansong@gmail.com>

* chore: image viewer cursor affordance

Signed-off-by: Evan Song <theevansong@gmail.com>

* chore: clean imports

Signed-off-by: Evan Song <theevansong@gmail.com>

* chore: add tooltips

Signed-off-by: Evan Song <theevansong@gmail.com>

* chore: use black background

Signed-off-by: Evan Song <theevansong@gmail.com>

* feat: show scale factor, handle large images, consolidate state

Signed-off-by: Evan Song <theevansong@gmail.com>

* chore: add types to fs operations

Signed-off-by: Evan Song <theevansong@gmail.com>

* feat: add date create sorting option

Signed-off-by: Evan Song <theevansong@gmail.com>

* fix: match name of folder creation modal

Signed-off-by: Evan Song <theevansong@gmail.com>

* fix: add it here too

Signed-off-by: Evan Song <theevansong@gmail.com>

* feat: add creation date to file item, file manager header

Signed-off-by: Evan Song <theevansong@gmail.com>

* chore: a11y

Signed-off-by: Evan Song <theevansong@gmail.com>

* fix: ensure move item modal always has leading slash

Signed-off-by: Evan Song <theevansong@gmail.com>

* fix: correct move input placeholder

Signed-off-by: Evan Song <theevansong@gmail.com>

* chore: correct design disparity

Signed-off-by: Evan Song <theevansong@gmail.com>

* chore: add better affordance on active file item state

Signed-off-by: Evan Song <theevansong@gmail.com>

* fix: correct instances where we dont sentence case

Signed-off-by: Evan Song <theevansong@gmail.com>

* chore: clean

Signed-off-by: Evan Song <theevansong@gmail.com>

* chore: notify that server restarted on saveandrestart

Signed-off-by: Evan Song <theevansong@gmail.com>

* fix: consolidate error state in file manager

Signed-off-by: Evan Song <theevansong@gmail.com>

* chore: adjust sizing

Signed-off-by: Evan Song <theevansong@gmail.com>

* feat: drag and drop file items to move them

Signed-off-by: Evan Song <theevansong@gmail.com>

* feat: enable ability to drag folders too

Signed-off-by: Evan Song <theevansong@gmail.com>

* feat: better file movement toasts

Signed-off-by: Evan Song <theevansong@gmail.com>

* just say u hate me

Signed-off-by: Evan Song <theevansong@gmail.com>

* feat: uploading indicator for file uploads

Signed-off-by: Evan Song <theevansong@gmail.com>

* chore: cleaner file item ghost when dragging

Signed-off-by: Evan Song <theevansong@gmail.com>

* fix: enforce max length and truncate on ghost

Signed-off-by: Evan Song <theevansong@gmail.com>

* chore: improve item rename toast

Signed-off-by: Evan Song <theevansong@gmail.com>

* chore: improve item create toast

Signed-off-by: Evan Song <theevansong@gmail.com>

* feat: undo and redo stack

Signed-off-by: Evan Song <theevansong@gmail.com>

* fix: confusing behavior where folders were not sorted alphabetically

Signed-off-by: Evan Song <theevansong@gmail.com>

* feat: find and replace in file editor

Signed-off-by: Evan Song <theevansong@gmail.com>

* feat: correctly set language mode of file editor

Signed-off-by: Evan Song <theevansong@gmail.com>

* chore: slop

Signed-off-by: Evan Song <theevansong@gmail.com>

* chore: actually handle case with multiple dots in file name before setting language

Signed-off-by: Evan Song <theevansong@gmail.com>

* fix: match move icons in file context/threedot

Signed-off-by: Evan Song <theevansong@gmail.com>

* feat: upload indicator

Signed-off-by: Evan Song <theevansong@gmail.com>

* chore: dedupe lockfile again

Signed-off-by: Evan Song <theevansong@gmail.com>

* lockfile

Signed-off-by: Evan Song <theevansong@gmail.com>

* fix: file undefinedness

Signed-off-by: Evan Song <theevansong@gmail.com>

* checkpoint

Signed-off-by: Evan Song <theevansong@gmail.com>

* checkpoint

Signed-off-by: Evan Song <theevansong@gmail.com>

* checkpoint

Signed-off-by: Evan Song <theevansong@gmail.com>

* remove shitty animation logic

Signed-off-by: Evan Song <theevansong@gmail.com>

* feat: file upload queuer

Signed-off-by: Evan Song <theevansong@gmail.com>

* chore: only allow editable files to have active affordance

Signed-off-by: Evan Song <theevansong@gmail.com>

* fix: properly throw pyrofetcherror when rename fails

Signed-off-by: Evan Song <theevansong@gmail.com>

* feat: cancel file uploads

Signed-off-by: Evan Song <theevansong@gmail.com>

* chore: clean

Signed-off-by: Evan Song <theevansong@gmail.com>

---------

Signed-off-by: Evan Song <theevansong@gmail.com>
This commit is contained in:
Evan Song
2024-12-16 16:13:31 -07:00
committed by GitHub
parent 9aa70359a8
commit fee8d6c34e
15 changed files with 1394 additions and 2539 deletions

View File

@@ -226,6 +226,21 @@ interface JWTAuth {
token: string;
}
export interface DirectoryItem {
name: string;
type: "directory" | "file";
count?: number;
modified: number;
created: number;
path: string;
}
export interface DirectoryResponse {
items: DirectoryItem[];
total: number;
current?: number;
}
type ContentType = "Mod" | "Plugin";
const constructServerProperties = (properties: any): string => {
@@ -738,6 +753,8 @@ const retryWithAuth = async (requestFn: () => Promise<any>) => {
await internalServerRefrence.value.refresh(["fs"]);
return await requestFn();
}
throw error;
}
};
@@ -763,21 +780,74 @@ const createFileOrFolder = (path: string, type: "file" | "directory") => {
};
const uploadFile = (path: string, file: File) => {
// eslint-disable-next-line require-await
return retryWithAuth(async () => {
const encodedPath = encodeURIComponent(path);
return await PyroFetch(`/create?path=${encodedPath}&type=file`, {
method: "POST",
contentType: "application/octet-stream",
body: file,
override: internalServerRefrence.value.fs.auth,
const progressSubject = new EventTarget();
const abortController = new AbortController();
const uploadPromise = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", (e) => {
if (e.lengthComputable) {
const progress = (e.loaded / e.total) * 100;
progressSubject.dispatchEvent(
new CustomEvent("progress", {
detail: {
loaded: e.loaded,
total: e.total,
progress,
},
}),
);
}
});
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response);
} else {
reject(new Error(`Upload failed with status ${xhr.status}`));
}
};
xhr.onerror = () => reject(new Error("Upload failed"));
xhr.onabort = () => reject(new Error("Upload cancelled"));
xhr.open(
"POST",
`https://${internalServerRefrence.value.fs.auth.url}/create?path=${encodedPath}&type=file`,
);
xhr.setRequestHeader("Authorization", `Bearer ${internalServerRefrence.value.fs.auth.token}`);
xhr.setRequestHeader("Content-Type", "application/octet-stream");
xhr.send(file);
abortController.signal.addEventListener("abort", () => {
xhr.abort();
});
});
return {
promise: uploadPromise,
onProgress: (
callback: (progress: { loaded: number; total: number; progress: number }) => void,
) => {
progressSubject.addEventListener("progress", ((e: CustomEvent) => {
callback(e.detail);
}) as EventListener);
},
cancel: () => {
abortController.abort();
},
};
});
};
const renameFileOrFolder = (path: string, name: string) => {
const pathName = path.split("/").slice(0, -1).join("/") + "/" + name;
return retryWithAuth(async () => {
return await PyroFetch(`/move`, {
await PyroFetch(`/move`, {
method: "POST",
override: internalServerRefrence.value.fs.auth,
body: {
@@ -785,6 +855,7 @@ const renameFileOrFolder = (path: string, name: string) => {
destination: pathName,
},
});
return true;
});
};
@@ -1235,7 +1306,7 @@ type FSFunctions = {
* @param pageSize - The page size to list.
* @returns
*/
listDirContents: (path: string, page: number, pageSize: number) => Promise<any>;
listDirContents: (path: string, page: number, pageSize: number) => Promise<DirectoryResponse>;
/**
* @param path - The path to create the file or folder at.