2023-12-07 20:27:40 +08:00

276 lines
7.4 KiB
JavaScript

import { createMachine, actions } from 'xstate';
import { ipcRenderer } from 'electron';
import prettyBytes from 'pretty-bytes';
import { uniqBy } from 'lodash';
import { message } from 'antd';
export default createMachine(
{
id: '微信视频号下载工具',
context: {
captureList: [],
currentUrl: '',
savePath: '',
downloadProgress: 0,
},
initial: '检测初始化',
states: {
检测初始化: {
id: '检测初始化',
invoke: {
src: 'invoke_初始化信息',
},
on: {
e_初始化完成: {
target: '初始化完成',
},
e_未初始化: {
target: '未初始化',
},
},
},
未初始化: {
initial: '空闲',
on: {
e_重新检测: {
target: '检测初始化',
},
},
states: {
空闲: {
on: {
e_开始初始化: {
target: '开始初始化',
},
},
},
开始初始化: {
invoke: {
src: 'invoke_开始初始化',
},
},
},
},
初始化完成: {
initial: '空闲',
id: '初始化完成',
invoke: {
src: 'invoke_启动服务',
},
on: {
e_视频捕获: {
actions: 'action_视频捕获',
},
e_开启服务失败: {
target: '开启服务失败',
},
e_清空捕获记录: {
actions: 'action_清空捕获记录',
},
},
states: {
空闲: {
on: {
e_下载: {
actions: 'action_设置当前地址',
target: '下载',
},
e_预览: {
actions: 'action_设置当前地址',
target: '预览',
},
e_改变规则: {
actions: 'action_改变规则',
},
},
},
下载: {
initial: '选择位置',
states: {
选择位置: {
on: {
e_确认位置: { actions: 'action_存储下载位置', target: '下载中' },
e_取消: { target: '#初始化完成.空闲' },
},
invoke: {
src: 'invoke_选择下载位置',
},
},
下载中: {
on: {
e_进度变化: {
actions: 'action_进度变化',
},
e_下载完成: {
target: '#初始化完成.空闲',
actions: 'action_下载完成',
},
e_下载失败: {
target: '#初始化完成.空闲',
actions: 'action_下载失败',
},
},
invoke: {
src: 'invoke_下载视频',
},
},
下载完成: {
on: {
e_取消: { target: '#初始化完成.空闲' },
e_打开文件位置: {
actions: 'action_打开文件位置',
},
},
},
},
},
预览: {
on: {
e_关闭: {
target: '空闲',
},
},
},
},
},
开启服务失败: {
on: {
e_重试: {
target: '初始化完成',
},
},
},
},
},
{
services: {
invoke_初始化信息: () => send => {
ipcRenderer.invoke('invoke_初始化信息').then(data => {
if (data === true) {
send('e_初始化完成');
} else {
send('e_未初始化');
}
});
},
invoke_开始初始化: (context, event) => send => {
ipcRenderer
.invoke('invoke_开始初始化')
.catch(() => {})
.finally(() => send('e_重新检测'));
},
invoke_启动服务: (context, event) => send => {
const fnDealVideoCapture = (eName, { url, size, description, decode_key, ...other }) => {
send({ type: 'e_视频捕获', url, size, description, decodeKey: decode_key, ...other });
};
ipcRenderer
.invoke('invoke_启动服务')
.then(() => {
ipcRenderer.on('VIDEO_CAPTURE', fnDealVideoCapture);
})
.catch(() => {
send('e_开启服务失败');
});
return () => {
ipcRenderer.removeListener('VIDEO_CAPTURE', fnDealVideoCapture);
};
},
invoke_选择下载位置: (context, event) => send => {
ipcRenderer
.invoke('invoke_选择下载位置')
.then(data => {
send({
type: 'e_确认位置',
data,
});
})
.catch(() => send('e_取消'));
},
invoke_下载视频:
({ currentUrl, savePath, decodeKey, description }) =>
send => {
ipcRenderer
.invoke('invoke_下载视频', {
url: currentUrl,
decodeKey,
savePath,
description,
})
.then(({ fullFileName }) => {
send({ type: 'e_下载完成', fullFileName, currentUrl });
})
.catch(() => {
send('e_下载失败');
});
ipcRenderer.on('e_进度变化', (event, arg) => {
send({
type: 'e_进度变化',
data: arg,
});
});
return () => {
ipcRenderer.removeAllListeners('e_进度变化');
};
},
},
actions: {
action_视频捕获: actions.assign(
({ captureList }, { url, size, description, decodeKey, ...other }) => {
captureList.push({
size,
url,
prettySize: prettyBytes(+size),
description,
decodeKey,
...other,
});
return {
captureList: uniqBy(captureList, 'url'),
};
},
),
action_清空捕获记录: actions.assign(() => {
return {
captureList: [],
};
}),
action_设置当前地址: actions.assign((_, { url, decodeKey, description }) => {
return {
currentUrl: url,
decodeKey: decodeKey,
description: description,
};
}),
action_存储下载位置: actions.assign((_, { data }) => {
return {
savePath: data,
};
}),
action_进度变化: actions.assign((_, { data }) => {
return {
downloadProgress: ~~(data * 100),
};
}),
action_下载完成: actions.assign(({ captureList }, { fullFileName, currentUrl }) => {
return {
captureList: captureList.map(item => {
if ((item.hdUrl || item.url) === currentUrl) {
item.fullFileName = fullFileName;
}
return item;
}),
};
}),
action_下载失败: actions.log(() => {
message.error('网络错误,请重试');
}),
},
},
);