8000 feat: improve task management, completed task will not re-start again by magicdawn · Pull Request #181 · buxuku/SmartSub · GitHub
[go: up one dir, main page]

Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
chore: revert main process code, do not persist formData inside IFiles
  • Loading branch information
magicdawn committed May 17, 2025
commit 5c1115504eddd68b615e3116f722ca405781108c
12 changes: 5 additions & 7 deletions main/helpers/fileProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ import {
generateSubtitleWithBuiltinWhisper,
} from './subtitleGenerator';
import translate from '../translate';
import type { IpcMainEvent } from 'electron';
import type { Provider, IFiles } from '../../types';
import { ensureTempDir, getMd5 } from './fileUtils';
import { IFiles } from '../../types';

/**
* 处理任务错误
Expand Down Expand Up @@ -82,13 +81,12 @@ async function translateSubtitle(event, file: IFiles, formData, provider) {
* 处理文件
*/
export async function processFile(
event: IpcMainEvent,
event,
file: IFiles,
hasOpenAiWhisper: boolean,
provider: Provider,
formData,
hasOpenAiWhisper,
provider,
) {
const { formData = {} } = file;

const {
sourceLanguage,
targetLanguage,
Expand Down
3 changes: 1 addition & 2 deletions main/helpers/taskManager.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ipcMain } from 'electron';
import type { IFiles } from '../../types';

let taskList: IFiles[] = [];
let taskList = [];

export function setupTaskManager() {
ipcMain.handle('getTasks', () => {
Expand Down
21 changes: 13 additions & 8 deletions main/helpers/taskProcessor.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import fse from 'fs-extra';
import { ipcMain, BrowserWindow, type IpcMainEvent } from 'electron';
import { ipcMain, BrowserWindow } from 'electron';
import { processFile } from './fileProcessor';
import { checkOpenAiWhisper, getPath } from './whisper';
import { logMessage, store } from './storeManager';
import path from 'path';
import { isAppleSilicon } from './utils';
import type { IFiles } from '../../types';
import { IFiles } from '../../types';

let processingQueue: IFiles[] = [];
let processingQueue = [];
let isProcessing = false;
let isPaused = false;
let shouldCancel = false;
Expand All @@ -22,7 +22,7 @@ export function setupTaskProcessor(mainWindow: BrowserWindow) {
console.log('handleTask start', files);
logMessage(`handleTask start`, 'info');
logMessage(`formData: \n ${JSON.stringify(formData, null, 2)}`, 'info');
processingQueue.push(...files);
processingQueue.push(...files.map((file) => ({ file, formData })));
if (!isProcessing) {
isProcessing = true;
isPaused = false;
Expand Down Expand Up @@ -72,7 +72,7 @@ export function setupTaskProcessor(mainWindow: BrowserWindow) {
});
}

async function processNextTasks(event: IpcMainEvent) {
async function processNextTasks(event) {
if (shouldCancel) {
isProcessing = false;
event.sender.send('taskComplete', 'cancelled');
Expand Down Expand Up @@ -103,11 +103,16 @@ async function processNextTasks(event: IpcMainEvent) {
activeTasksCount++;
try {
const provider = translationProviders.find(
(p) => p.id === task.formData?.translateProvider,
(p) => p.id === task.formData.translateProvider,
);
await processFile(
event,
task.file as IFiles,
task.formData,
hasOpenAiWhisper,
provider,
);
await processFile(event, task, hasOpenAiWhisper, provider);
} catch (error) {
console.error(error.stack || error);
event.sender.send('message', error);
} finally {
activeTasksCount--;
Expand Down
120 changes: 120 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"@radix-ui/react-tabs": "^1.1.4",
"@radix-ui/react-tooltip": "^1.0.7",
"@volcengine/openapi": "^1.18.3",
"ahooks": "^3.8.4",
"axios": "^1.6.8",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
Expand Down
71 changes: 58 additions & 13 deletions renderer/components/TaskControls.tsx
AA41
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,21 @@ import { toast } from 'sonner';
import { getNewTaskFiles, needsCoreML } from 'lib/utils';
import { useTranslation } from 'next-i18next';
import type { IFiles } from '../../types';
import { Switch } from './ui/switch';
import useLocalStorageState from 'hooks/useLocalStorageState';
import { useUpdateEffect } from 'ahooks';

type TaskStatus = 'idle' | 'running' | 'paused' | 'cancelled' | 'completed';

const TaskControls: FC<{
files: IFiles[];
setFiles: Dispatch<SetStateAction<IFiles[]>>;
formData: any;
}> = ({ files, setFiles, formData }) => {
const [taskStatus, setTaskStatus] = useState('idle');
const [taskStatus, setTaskStatus] = useState<TaskStatus>('idle');
const { t } = useTranslation(['home', 'common']);
const [autoStartNewTaskWhenRunning, setAutoStartNewTaskWhenRunning] =
useLocalStorageState<boolean>('auto-start-new-task-when-running', false);

useEffect(() => {
// 获取当前任务状态
Expand All @@ -28,7 +35,7 @@ const TaskControls: FC<{
getCurrentTaskStatus();

// 监听任务状态变化
const cleanup = window?.ipc?.on('taskComplete', (status: string) => {
const cleanup = window?.ipc?.on('taskComplete', (status: TaskStatus) => {
setTaskStatus(status);
});

Expand All @@ -37,22 +44,30 @@ const TaskControls: FC<{
};
}, []);

const handleTask = async () => {
const handleTask = async (options?: { silentNoNewTask?: boolean }) => {
if (!files?.length) {
return toast(t('common:notification'), { description: t('home:noTask') });
}

// when start task button pressed, persist task config to IFiles
const updatedFiles = files.map((f) => {
return { formData, taskType: formData.taskType, ...f };
});
setFiles(updatedFiles);
// when start task button pressed, persist taskType to IFiles
const needPersist = files.some((f) => !f.taskType);
let updatedFiles = files;
if (needPersist) {
updatedFiles = files.map((f) => {
if (f.taskType) return f;
return { ...f, taskType: formData.taskType };
});
setFiles(updatedFiles);
}

const newTaskFiles = getNewTaskFiles(updatedFiles);
if (!newTaskFiles.length) {
return toast(t('common:notification'), {
description: t('home:allFilesProcessed'),
});
if (!options?.silentNoNewTask) {
toast(t('common:notification'), {
description: t('home:allFilesProcessed'),
});
}
return;
}

// if(formData.model && needsCoreML(formData.model)){
Expand All @@ -66,6 +81,12 @@ const TaskControls: FC<{
// }

setTaskStatus('running');
setFiles((files) =>
files.map((f) => {
if (f.sent) return f;
return { ...f, sent: true };
}),
);
window?.ipc?.send('handleTask', { files: newTaskFiles, formData });
};
const handlePause = () => {
Expand All @@ -82,15 +103,39 @@ const TaskControls: FC<{
window?.ipc?.send('cancelTask', null);
setTaskStatus('cancelled');
};

useUpdateEffect(() => {
if (
taskStatus === 'running' &&
autoStartNewTaskWhenRunning &&
files.length
) {
handleTask({ silentNoNewTask: true });
}
}, [files.length]);

return (
<div className="flex gap-2 ml-auto">
{(taskStatus === 'idle' || taskStatus === 'completed') && (
<Button onClick={handleTask} disabled={!files.length}>
<Button onClick={() => handleTask()} disabled={!files.length}>
{t('home:startTask')}
</Button>
)}
{taskStatus === 'running' && (
<>
<span className="inline-flex items-center justify-center gap-x-1 mr-1">
<Switch
id="auto-start-new-task-when-running"
checked={autoStartNewTaskWhenRunning}
onCheckedChange={setAutoStartNewTaskWhenRunning}
/>
<label
htmlFor="auto-start-new-task-when-running"
className="cursor-pointer select-none"
>
{t('home:autoStartNewTaskWhenRunning')}
</label>
</span>
<Button onClick={handlePause}>{t('home:pauseTask')}</Button>
<Button onClick={handleCancel}>{t('home:cancelTask')}</Button>
</>
Expand All @@ -102,7 +147,7 @@ const TaskControls: FC<{
</>
)}
{taskStatus === 'cancelled' && (
<Button onClick={handleTask} disabled={!files.length}>
<Button onClick={() => handleTask()} disabled={!files.length}>
{t('home:restartTask')}
</Button>
)}
Expand Down
1 change: 1 addition & 0 deletions renderer/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ function fileStatusGetters(file: IFiles) {

export function getNewTaskFiles(files: IFiles[]) {
return files.filter((file) => {
if (!file.sent) return true; // not sent yet
const { running, succeed } = fileStatusGetters(file);
if (running) return false;
if (succeed) return false;
Expand Down
3 changes: 2 additions & 1 deletion renderer/public/locales/en/home.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,6 @@
"total": "Total",
"translated": "Translated",
"completionRate": "Completion rate",
"originalSubtitle": "Original subtitle"
"originalSubtitle": "Original subtitle",
"autoStartNewTaskWhenRunning": "Auto tart new tasks"
}
3 changes: 2 additions & 1 deletion renderer/public/locales/zh/home.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,5 +112,6 @@
"total": "总数",
"translated": "已翻译",
"completionRate": "完成率",
"originalSubtitle": "原文字幕"
"originalSubtitle": "原文字幕",
"autoStartNewTaskWhenRunning": "自动开始新任务"
}
2 changes: 1 addition & 1 deletion types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ export interface IFiles {
translatedSrtFile?: string;
tempTranslatedSrtFile?: string;

sent?: boolean; // 是否已发送
taskType?: ITaskType;
formData?: any; // 任务配置
}

export interface IFormData {
Expand Down
Loading
0