import React, { useEffect, useMemo } from 'react' import { useState } from 'react' import { Button, createTableColumn, Dialog, DialogActions, DialogBody, DialogContent, DialogSurface, DialogTitle, DialogTrigger, Field, Input, Radio, RadioGroup, TableColumnDefinition, TableColumnSizingOptions, useTableColumnSizing_unstable, useTableFeatures, } from '@fluentui/react-components' import { TableBody, TableCell, TableRow, Table, TableHeader, TableHeaderCell, TableCellLayout, makeStyles, tokens, } from '@fluentui/react-components' import { ClockRegular, CheckmarkRegular, DismissRegular, DocumentArrowRightRegular, DocumentAddRegular, DeleteRegular, DeleteDismissRegular, FolderAddRegular, WindowPlayRegular, } from '@fluentui/react-icons' import { Status, Item, SaveTo } from './types' import { SelectFiles, SelectFolder, SelectFilesFromFolder, ProcessFiles } from '../wailsjs/go/main/App' import { Load, Save } from '../wailsjs/go/utils/ConfigManager' import { main } from '../wailsjs/go/models' import { EventsOn, OnFileDrop } from '../wailsjs/runtime/runtime' const columnsDef: TableColumnDefinition[] = [ createTableColumn({ columnId: 'status', renderHeaderCell: () => <>状态, }), createTableColumn({ columnId: 'file', renderHeaderCell: () => <>文件, }), createTableColumn({ columnId: 'operation', renderHeaderCell: () => <>操作, }), ] const useStyles = makeStyles({ iconGreen: { color: tokens.colorPaletteGreenForeground1, }, iconRed: { color: tokens.colorPaletteRedForeground1, }, iconYellow: { color: tokens.colorPaletteYellowForeground1, }, }) let loaded = false export const App = () => { const styles = useStyles() const [items, setItems] = useState([]) const isProcessing = useMemo(() => { return items.some(item => item.status === 'processing') }, [items]) const [saveTo, setSaveTo] = useState('original') const [savePath, setSavePath] = useState('') const [message, setMessage] = useState('') const [open, setOpen] = useState(false) const [columns] = React.useState[]>(columnsDef) const [columnSizingOptions] = React.useState({ status: { idealWidth: 100, minWidth: 100, }, file: { idealWidth: 1000, minWidth: 150, }, operation: { idealWidth: 80, minWidth: 80, }, }) // eslint-disable-next-line @typescript-eslint/naming-convention const { getRows, columnSizing_unstable, tableRef } = useTableFeatures( { columns, items, }, [useTableColumnSizing_unstable({ columnSizingOptions })] ) // return the icon based on the status const statusMapIcon = (status: Status) => { switch (status) { case 'pending': return case 'processing': return case 'done': return case 'error': return default: } } // return the text based on the status const statusMapText = (status: Status) => { switch (status) { case 'pending': return '等待' case 'processing': return '处理' case 'done': return '完成' case 'error': return '错误' } } const selectFiles = () => { if (isProcessing) { return } SelectFiles().then(files => { for (const file of files) { setItems(prev => [...prev, { file, status: 'pending' }]) } }) } const selectFilesFromFolder = () => { if (isProcessing) { return } SelectFilesFromFolder('ncm').then(files => { for (const file of files) { setItems(prev => [...prev, { file, status: 'pending' }]) } }) } const showDialog = (message: string) => { setMessage(message) setOpen(true) } const startProcess = async () => { // 未添加文件时 if (items.length === 0) { showDialog('当前文件列表为空,请先添加文件。') return } // 检查所有文件是否都已处理完毕 let isAllFinished = true for (const item of items) { if (item.status === 'pending') { isAllFinished = false break } } if (isAllFinished) { showDialog('当前文件列表已全部处理完毕,请重新添加新的文件。') return } if (saveTo === 'custom' && savePath === '') { showDialog('保存路径为空,请先设置保存路径。') return } const ncmFiles: main.NcmFile[] = [] items.forEach(item => { ncmFiles.push({ Name: item.file, Status: item.status, }) }) ProcessFiles(ncmFiles, savePath).then(() => {}) } useEffect(() => { EventsOn('file-status-changed', (index: number, status: Status) => { setItems(prev => { const newItems = [...prev] newItems[index].status = status return newItems }) }) Load().then(res => { setSaveTo(res.save_to as SaveTo) setSavePath(res.path) loaded = true }) }, []) useEffect(() => { if (loaded) { Save({ save_to: saveTo, path: savePath, }).then(_ => {}) } }, [saveTo, savePath]) OnFileDrop((_x, _y, paths) => { let length = paths.length for (const path of paths) { // only end with ncm if (!path.endsWith('.ncm')) { length-- continue } setItems(prev => [...prev, { file: path, status: 'pending' }]) } }, false) return (
{ // it is the users responsibility to react accordingly to the open state change setOpen(data.open) }} > 警告 {message}
{ setSaveTo(data.value as SaveTo) if (data.value === 'original') { setSavePath('') } }} > {saveTo === 'custom' && ( { SelectFolder().then(path => { if (path) { setSavePath(path) } }) }} /> )}
{columns.map(column => ( {column.renderHeaderCell()} ))} {items.map((file, index) => ( {statusMapText(file.status)} {file.file} ))}
) } export default App