optimize fm (#82)

* optimize fm

* chore: auto-fix linting and formatting issues

* fix: type

* chore: auto-fix linting and formatting issues

---------

Co-authored-by: uubulb <uubulb@users.noreply.github.com>
Co-authored-by: naiba <hi@nai.ba>
Co-authored-by: naiba <naiba@users.noreply.github.com>
This commit is contained in:
UUBulb
2024-12-29 22:19:50 +08:00
committed by GitHub
parent 97a5deb648
commit 01add8b160
12 changed files with 164 additions and 120 deletions
+66 -50
View File
@@ -41,6 +41,7 @@ import { HTMLAttributes, useEffect, useRef, useState } from "react"
import { useTranslation } from "react-i18next"
import { toast } from "sonner"
import { Button } from "./ui/button"
import { TableCell, TableRow } from "./ui/table"
import { Filepath } from "./xui/filepath"
import { IconButton } from "./xui/icon-button"
@@ -102,7 +103,7 @@ const FMComponent: React.FC<FMProps & JSX.IntrinsicElements["div"]> = ({ wsUrl,
header: () => <span>{t("Actions")}</span>,
id: "download",
cell: ({ row }) => {
return (
return row.original.type == 0 ? (
<IconButton
variant="ghost"
icon="download"
@@ -111,6 +112,8 @@ const FMComponent: React.FC<FMProps & JSX.IntrinsicElements["div"]> = ({ wsUrl,
downloadFile(row.original.name)
}}
/>
) : (
<Button size="icon" variant="ghost" className="pointer-events-none" />
)
},
},
@@ -157,42 +160,6 @@ const FMComponent: React.FC<FMProps & JSX.IntrinsicElements["div"]> = ({ wsUrl,
}
}
worker.onmessage = async (event: MessageEvent<FMWorkerData>) => {
switch (event.data.type) {
case FMWorkerOpcode.Error: {
console.error("Error from worker", event.data.error)
break
}
case FMWorkerOpcode.Progress: {
handleReady.current = true
break
}
case FMWorkerOpcode.Result: {
handleReady.current = false
if (event.data.blob && event.data.fileName) {
const url = URL.createObjectURL(event.data.blob)
const anchor = document.createElement("a")
anchor.href = url
anchor.download = event.data.fileName
anchor.click()
URL.revokeObjectURL(url)
}
firstChunk.current = true
if (dOpen) setdOpen(false)
break
}
}
}
const [currentPath, setPath] = useState("")
useEffect(() => {
if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {
listFile()
}
}, [wsRef.current, currentPath])
useEffect(() => {
const ws = new WebSocket(wsUrl)
wsRef.current = ws
@@ -209,27 +176,27 @@ const FMComponent: React.FC<FMProps & JSX.IntrinsicElements["div"]> = ({ wsUrl,
description: t("Results.UnExpectedError"),
})
}
ws.onmessage = async (e) => {
ws.onmessage = async (e: MessageEvent<ArrayBufferLike>) => {
try {
const buf: ArrayBufferLike = e.data
const identifier = new Uint8Array(e.data, 0, 4)
if (arraysEqual(identifier, FMIdentifier.error)) {
const errBytes = e.data.slice(4)
const errMsg = new TextDecoder("utf-8").decode(errBytes)
throw new Error(errMsg)
}
if (firstChunk.current) {
const identifier = new Uint8Array(buf, 0, 4)
if (arraysEqual(identifier, FMIdentifier.file)) {
worker.postMessage({
operation: 1,
arrayBuffer: buf,
arrayBuffer: e.data,
fileName: currentBasename.current,
})
firstChunk.current = false
} else if (arraysEqual(identifier, FMIdentifier.fileName)) {
const { path, fmList } = await fm.parseFMList(buf)
const { path, fmList } = await fm.parseFMList(e.data)
setPath(path)
setFMEntries(fmList)
} else if (arraysEqual(identifier, FMIdentifier.error)) {
const errBytes = buf.slice(4)
const errMsg = new TextDecoder("utf-8").decode(errBytes)
throw new Error(errMsg)
} else if (arraysEqual(identifier, FMIdentifier.complete)) {
// Upload completed
if (uOpen) setuOpen(false)
@@ -241,7 +208,7 @@ const FMComponent: React.FC<FMProps & JSX.IntrinsicElements["div"]> = ({ wsUrl,
await waitForHandleReady()
worker.postMessage({
operation: 2,
arrayBuffer: buf,
arrayBuffer: e.data,
fileName: currentBasename.current,
})
}
@@ -250,12 +217,61 @@ const FMComponent: React.FC<FMProps & JSX.IntrinsicElements["div"]> = ({ wsUrl,
toast("FM" + " " + t("Error"), {
description: t("Results.UnExpectedError"),
})
if (dOpen) setdOpen(false)
if (uOpen) setuOpen(false)
setdOpen(false)
setuOpen(false)
}
}
}, [wsUrl])
useEffect(() => {
worker.onmessage = async (event: MessageEvent<FMWorkerData>) => {
switch (event.data.type) {
case FMWorkerOpcode.Error: {
console.error("Error from worker", event.data.error)
break
}
case FMWorkerOpcode.Progress: {
handleReady.current = true
break
}
case FMWorkerOpcode.Result: {
handleReady.current = false
if (event.data.blob && event.data.fileName) {
const url = URL.createObjectURL(event.data.blob)
const anchor = document.createElement("a")
anchor.href = url
anchor.download = event.data.fileName
anchor.click()
URL.revokeObjectURL(url)
}
firstChunk.current = true
if (dOpen) setdOpen(false)
break
}
}
}
const handleBeforeUnload = () => {
worker.postMessage({
operation: 3,
})
}
window.addEventListener("beforeunload", handleBeforeUnload)
return () => {
window.removeEventListener("beforeunload", handleBeforeUnload)
}
}, [worker, dOpen])
const [currentPath, setPath] = useState("")
useEffect(() => {
if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {
listFile()
}
}, [wsRef.current, currentPath])
const listFile = () => {
const prefix = new Int8Array([FMOpcode.List])
const pathMsg = new TextEncoder().encode(currentPath)
@@ -317,7 +333,7 @@ const FMComponent: React.FC<FMProps & JSX.IntrinsicElements["div"]> = ({ wsUrl,
toast("FM" + " " + t("Error"), {
description: error.message,
})
console.log("copy error: ", error)
console.error("copy error: ", error)
}
}}
>