mirror of
https://wget.la/https://github.com/Wxw-Gu/WechatExplorer
synced 2026-10-05 12:34:35 +08:00
feat: 增加一个查找语音文件
This commit is contained in:
@@ -1336,6 +1336,51 @@ app.whenReady().then(async () => {
|
||||
}
|
||||
)
|
||||
|
||||
ipcMain.handle(
|
||||
'voice:showSourceContextMenu',
|
||||
(
|
||||
event,
|
||||
reference: { sessionId: string; localId: number; createTime: number; svrId?: string | number }
|
||||
) => {
|
||||
const window = BrowserWindow.fromWebContents(event.sender)
|
||||
if (!window || !voiceService) return { success: false, error: '语音服务未初始化' }
|
||||
|
||||
const revealSource = async (): Promise<void> => {
|
||||
try {
|
||||
const result = await voiceService!.resolveSource(
|
||||
reference.sessionId,
|
||||
reference.localId,
|
||||
reference.createTime,
|
||||
reference.svrId
|
||||
)
|
||||
if (!result.success) throw new Error(result.error)
|
||||
|
||||
const directory = join(app.getPath('userData'), 'voice-sources')
|
||||
await fsPromises.mkdir(directory, { recursive: true })
|
||||
const fileName = `voice_${reference.localId}_${reference.createTime}_${result.source.sourceHash.slice(0, 12)}.silk`
|
||||
const filePath = join(directory, fileName)
|
||||
await fsPromises.writeFile(filePath, result.source.data)
|
||||
shell.showItemInFolder(filePath)
|
||||
} catch (error) {
|
||||
await dialog.showMessageBox(window, {
|
||||
type: 'error',
|
||||
title: '查找语音源文件失败',
|
||||
message: '无法提取这条语音的源文件',
|
||||
detail: error instanceof Error ? error.message : String(error)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Menu.buildFromTemplate([
|
||||
{
|
||||
label: '查找语音源文件',
|
||||
click: () => void revealSource()
|
||||
}
|
||||
]).popup({ window })
|
||||
return { success: true }
|
||||
}
|
||||
)
|
||||
|
||||
ipcMain.handle('voice:getModelStatus', async () => {
|
||||
if (!voiceRecognition) throw new Error('Voice recognition is not initialized')
|
||||
return voiceRecognition.getModelStatus()
|
||||
|
||||
Vendored
+3
@@ -307,6 +307,9 @@ declare global {
|
||||
createTime: number,
|
||||
svrId?: string | number
|
||||
) => Promise<{ success: boolean; data?: string; error?: string }>
|
||||
showVoiceSourceContextMenu: (
|
||||
reference: VoiceMessageReference
|
||||
) => Promise<{ success: boolean; error?: string }>
|
||||
getVoiceModelStatus: () => Promise<VoiceModelStatus>
|
||||
downloadVoiceModel: () => Promise<VoiceModelDownloadResult>
|
||||
cancelVoiceModelDownload: () => Promise<{ success: boolean }>
|
||||
|
||||
@@ -178,6 +178,8 @@ const api = {
|
||||
copyImage: (base64String) => ipcRenderer.invoke('copy-image', base64String),
|
||||
getVoiceData: (sessionId: string, localId: number, createTime: number, svrId?: string | number) =>
|
||||
ipcRenderer.invoke('db:getVoiceData', sessionId, localId, createTime, svrId),
|
||||
showVoiceSourceContextMenu: (reference: VoiceMessageReference) =>
|
||||
ipcRenderer.invoke('voice:showSourceContextMenu', reference),
|
||||
getVoiceModelStatus: (): Promise<VoiceModelStatus> => ipcRenderer.invoke('voice:getModelStatus'),
|
||||
downloadVoiceModel: (): Promise<VoiceModelDownloadResult> =>
|
||||
ipcRenderer.invoke('voice:downloadModel'),
|
||||
|
||||
@@ -193,6 +193,15 @@ export function VoicePlayer({
|
||||
window.dispatchEvent(new Event('wxe:open-voice-recognition-settings'))
|
||||
}, [])
|
||||
|
||||
const handleContextMenu = useCallback(
|
||||
(event: ReactMouseEvent<HTMLDivElement>) => {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
void window.api.showVoiceSourceContextMenu(voiceReference)
|
||||
},
|
||||
[voiceReference]
|
||||
)
|
||||
|
||||
const formatDuration = (seconds: number | undefined): string => {
|
||||
if (!seconds || !isFinite(seconds)) return '0:00'
|
||||
const mins = Math.floor(seconds / 60)
|
||||
@@ -205,6 +214,7 @@ export function VoicePlayer({
|
||||
<div
|
||||
className={`voice-message ${loading ? 'voice-loading' : ''} ${error && !audioUrl ? 'voice-error' : ''}`}
|
||||
onClick={handlePlayPause}
|
||||
onContextMenu={handleContextMenu}
|
||||
>
|
||||
<span className={`voice-icon ${isPlaying ? 'playing' : ''}`}>{isPlaying ? '⏸' : '▶'}</span>
|
||||
{loading ? (
|
||||
|
||||
Reference in New Issue
Block a user