mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-04-04 15:08:14 +00:00
Compare commits
1 Commits
dev
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12be5311ce |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -72,4 +72,3 @@ pnpm-lock.yaml
|
|||||||
/pnpm-workspace.yaml
|
/pnpm-workspace.yaml
|
||||||
wechat-research-site
|
wechat-research-site
|
||||||
.codex
|
.codex
|
||||||
weflow-web-offical
|
|
||||||
@@ -136,7 +136,6 @@ const shouldOfferUpdateForTrack = (latestVersion: string, currentVersion: string
|
|||||||
}
|
}
|
||||||
|
|
||||||
let lastAppliedUpdaterChannel: string | null = null
|
let lastAppliedUpdaterChannel: string | null = null
|
||||||
let lastAppliedUpdaterFeedUrl: string | null = null
|
|
||||||
const resetUpdaterProviderCache = () => {
|
const resetUpdaterProviderCache = () => {
|
||||||
const updater = autoUpdater as any
|
const updater = autoUpdater as any
|
||||||
// electron-updater 会缓存 provider;切换 channel 后需清理缓存,避免仍请求旧通道
|
// electron-updater 会缓存 provider;切换 channel 后需清理缓存,避免仍请求旧通道
|
||||||
@@ -147,41 +146,23 @@ const resetUpdaterProviderCache = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getUpdaterFeedUrlByTrack = (track: 'stable' | 'preview' | 'dev'): string => {
|
|
||||||
const repoBase = 'https://github.com/hicccc77/WeFlow/releases'
|
|
||||||
if (track === 'stable') return `${repoBase}/latest/download`
|
|
||||||
if (track === 'preview') return `${repoBase}/download/nightly-preview`
|
|
||||||
return `${repoBase}/download/nightly-dev`
|
|
||||||
}
|
|
||||||
|
|
||||||
const applyAutoUpdateChannel = (reason: 'startup' | 'settings' = 'startup') => {
|
const applyAutoUpdateChannel = (reason: 'startup' | 'settings' = 'startup') => {
|
||||||
const track = getEffectiveUpdateTrack()
|
const track = getEffectiveUpdateTrack()
|
||||||
const currentTrack = inferUpdateTrackFromVersion(appVersion)
|
const currentTrack = inferUpdateTrackFromVersion(appVersion)
|
||||||
const baseUpdateChannel = track === 'stable' ? 'latest' : track
|
const baseUpdateChannel = track === 'stable' ? 'latest' : track
|
||||||
const nextFeedUrl = getUpdaterFeedUrlByTrack(track)
|
|
||||||
const nextUpdaterChannel =
|
const nextUpdaterChannel =
|
||||||
process.platform === 'win32' && process.arch === 'arm64'
|
process.platform === 'win32' && process.arch === 'arm64'
|
||||||
? `${baseUpdateChannel}-arm64`
|
? `${baseUpdateChannel}-arm64`
|
||||||
: baseUpdateChannel
|
: baseUpdateChannel
|
||||||
if (
|
if (lastAppliedUpdaterChannel && lastAppliedUpdaterChannel !== nextUpdaterChannel) {
|
||||||
(lastAppliedUpdaterChannel && lastAppliedUpdaterChannel !== nextUpdaterChannel) ||
|
|
||||||
(lastAppliedUpdaterFeedUrl && lastAppliedUpdaterFeedUrl !== nextFeedUrl)
|
|
||||||
) {
|
|
||||||
resetUpdaterProviderCache()
|
resetUpdaterProviderCache()
|
||||||
}
|
}
|
||||||
autoUpdater.allowPrerelease = track !== 'stable'
|
autoUpdater.allowPrerelease = track !== 'stable'
|
||||||
// 只要用户当前选择的目标通道与当前安装版本所属通道不同,就允许跨通道更新(含降级)
|
// 只要用户当前选择的目标通道与当前安装版本所属通道不同,就允许跨通道更新(含降级)
|
||||||
autoUpdater.allowDowngrade = track !== currentTrack
|
autoUpdater.allowDowngrade = track !== currentTrack
|
||||||
// 统一走 generic feed,确保 preview/dev 命中各自固定发布页,不受 GitHub provider 的 prerelease 选择影响。
|
|
||||||
autoUpdater.setFeedURL({
|
|
||||||
provider: 'generic',
|
|
||||||
url: nextFeedUrl,
|
|
||||||
channel: nextUpdaterChannel
|
|
||||||
})
|
|
||||||
autoUpdater.channel = nextUpdaterChannel
|
autoUpdater.channel = nextUpdaterChannel
|
||||||
lastAppliedUpdaterChannel = nextUpdaterChannel
|
lastAppliedUpdaterChannel = nextUpdaterChannel
|
||||||
lastAppliedUpdaterFeedUrl = nextFeedUrl
|
console.log(`[Update](${reason}) 当前版本 ${appVersion},当前轨道: ${currentTrack},渠道偏好: ${track},更新通道: ${autoUpdater.channel},allowDowngrade=${autoUpdater.allowDowngrade}`)
|
||||||
console.log(`[Update](${reason}) 当前版本 ${appVersion},当前轨道: ${currentTrack},渠道偏好: ${track},更新通道: ${autoUpdater.channel},feed=${nextFeedUrl},allowDowngrade=${autoUpdater.allowDowngrade}`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
applyAutoUpdateChannel('startup')
|
applyAutoUpdateChannel('startup')
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ export interface Message {
|
|||||||
fileName?: string // 文件名
|
fileName?: string // 文件名
|
||||||
fileSize?: number // 文件大小
|
fileSize?: number // 文件大小
|
||||||
fileExt?: string // 文件扩展名
|
fileExt?: string // 文件扩展名
|
||||||
fileMd5?: string // 文件 MD5
|
|
||||||
xmlType?: string // XML 中的 type 字段
|
xmlType?: string // XML 中的 type 字段
|
||||||
appMsgKind?: string // 归一化 appmsg 类型
|
appMsgKind?: string // 归一化 appmsg 类型
|
||||||
appMsgDesc?: string
|
appMsgDesc?: string
|
||||||
@@ -3797,7 +3796,6 @@ class ChatService {
|
|||||||
let fileName: string | undefined
|
let fileName: string | undefined
|
||||||
let fileSize: number | undefined
|
let fileSize: number | undefined
|
||||||
let fileExt: string | undefined
|
let fileExt: string | undefined
|
||||||
let fileMd5: string | undefined
|
|
||||||
let xmlType: string | undefined
|
let xmlType: string | undefined
|
||||||
let appMsgKind: string | undefined
|
let appMsgKind: string | undefined
|
||||||
let appMsgDesc: string | undefined
|
let appMsgDesc: string | undefined
|
||||||
@@ -3902,7 +3900,6 @@ class ChatService {
|
|||||||
fileName = type49Info.fileName
|
fileName = type49Info.fileName
|
||||||
fileSize = type49Info.fileSize
|
fileSize = type49Info.fileSize
|
||||||
fileExt = type49Info.fileExt
|
fileExt = type49Info.fileExt
|
||||||
fileMd5 = type49Info.fileMd5
|
|
||||||
chatRecordTitle = type49Info.chatRecordTitle
|
chatRecordTitle = type49Info.chatRecordTitle
|
||||||
chatRecordList = type49Info.chatRecordList
|
chatRecordList = type49Info.chatRecordList
|
||||||
transferPayerUsername = type49Info.transferPayerUsername
|
transferPayerUsername = type49Info.transferPayerUsername
|
||||||
@@ -3926,7 +3923,6 @@ class ChatService {
|
|||||||
fileName = fileName || type49Info.fileName
|
fileName = fileName || type49Info.fileName
|
||||||
fileSize = fileSize ?? type49Info.fileSize
|
fileSize = fileSize ?? type49Info.fileSize
|
||||||
fileExt = fileExt || type49Info.fileExt
|
fileExt = fileExt || type49Info.fileExt
|
||||||
fileMd5 = fileMd5 || type49Info.fileMd5
|
|
||||||
appMsgKind = appMsgKind || type49Info.appMsgKind
|
appMsgKind = appMsgKind || type49Info.appMsgKind
|
||||||
appMsgDesc = appMsgDesc || type49Info.appMsgDesc
|
appMsgDesc = appMsgDesc || type49Info.appMsgDesc
|
||||||
appMsgAppName = appMsgAppName || type49Info.appMsgAppName
|
appMsgAppName = appMsgAppName || type49Info.appMsgAppName
|
||||||
@@ -4000,7 +3996,6 @@ class ChatService {
|
|||||||
fileName,
|
fileName,
|
||||||
fileSize,
|
fileSize,
|
||||||
fileExt,
|
fileExt,
|
||||||
fileMd5,
|
|
||||||
xmlType,
|
xmlType,
|
||||||
appMsgKind,
|
appMsgKind,
|
||||||
appMsgDesc,
|
appMsgDesc,
|
||||||
@@ -4604,7 +4599,6 @@ class ChatService {
|
|||||||
fileName?: string
|
fileName?: string
|
||||||
fileSize?: number
|
fileSize?: number
|
||||||
fileExt?: string
|
fileExt?: string
|
||||||
fileMd5?: string
|
|
||||||
transferPayerUsername?: string
|
transferPayerUsername?: string
|
||||||
transferReceiverUsername?: string
|
transferReceiverUsername?: string
|
||||||
chatRecordTitle?: string
|
chatRecordTitle?: string
|
||||||
@@ -4801,7 +4795,6 @@ class ChatService {
|
|||||||
|
|
||||||
// 提取文件扩展名
|
// 提取文件扩展名
|
||||||
const fileExt = this.extractXmlValue(content, 'fileext')
|
const fileExt = this.extractXmlValue(content, 'fileext')
|
||||||
const fileMd5 = this.extractXmlValue(content, 'md5') || this.extractXmlValue(content, 'filemd5')
|
|
||||||
if (fileExt) {
|
if (fileExt) {
|
||||||
result.fileExt = fileExt
|
result.fileExt = fileExt
|
||||||
} else if (result.fileName) {
|
} else if (result.fileName) {
|
||||||
@@ -4811,9 +4804,6 @@ class ChatService {
|
|||||||
result.fileExt = match[1]
|
result.fileExt = match[1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fileMd5) {
|
|
||||||
result.fileMd5 = fileMd5.toLowerCase()
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,8 +98,6 @@ export interface ExportOptions {
|
|||||||
exportVoices?: boolean
|
exportVoices?: boolean
|
||||||
exportVideos?: boolean
|
exportVideos?: boolean
|
||||||
exportEmojis?: boolean
|
exportEmojis?: boolean
|
||||||
exportFiles?: boolean
|
|
||||||
maxFileSizeMb?: number
|
|
||||||
exportVoiceAsText?: boolean
|
exportVoiceAsText?: boolean
|
||||||
excelCompactColumns?: boolean
|
excelCompactColumns?: boolean
|
||||||
txtColumns?: string[]
|
txtColumns?: string[]
|
||||||
@@ -123,7 +121,7 @@ const TXT_COLUMN_DEFINITIONS: Array<{ id: string; label: string }> = [
|
|||||||
|
|
||||||
interface MediaExportItem {
|
interface MediaExportItem {
|
||||||
relativePath: string
|
relativePath: string
|
||||||
kind: 'image' | 'voice' | 'emoji' | 'video' | 'file'
|
kind: 'image' | 'voice' | 'emoji' | 'video'
|
||||||
posterDataUrl?: string
|
posterDataUrl?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,11 +136,6 @@ interface ExportDisplayProfile {
|
|||||||
|
|
||||||
type MessageCollectMode = 'full' | 'text-fast' | 'media-fast'
|
type MessageCollectMode = 'full' | 'text-fast' | 'media-fast'
|
||||||
type MediaContentType = 'voice' | 'image' | 'video' | 'emoji'
|
type MediaContentType = 'voice' | 'image' | 'video' | 'emoji'
|
||||||
interface FileExportCandidate {
|
|
||||||
sourcePath: string
|
|
||||||
matchedBy: 'md5' | 'name'
|
|
||||||
yearMonth?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ExportProgress {
|
export interface ExportProgress {
|
||||||
current: number
|
current: number
|
||||||
@@ -849,7 +842,7 @@ class ExportService {
|
|||||||
|
|
||||||
private isMediaExportEnabled(options: ExportOptions): boolean {
|
private isMediaExportEnabled(options: ExportOptions): boolean {
|
||||||
return options.exportMedia === true &&
|
return options.exportMedia === true &&
|
||||||
Boolean(options.exportImages || options.exportVoices || options.exportVideos || options.exportEmojis || options.exportFiles)
|
Boolean(options.exportImages || options.exportVoices || options.exportVideos || options.exportEmojis)
|
||||||
}
|
}
|
||||||
|
|
||||||
private isUnboundedDateRange(dateRange?: { start: number; end: number } | null): boolean {
|
private isUnboundedDateRange(dateRange?: { start: number; end: number } | null): boolean {
|
||||||
@@ -887,7 +880,7 @@ class ExportService {
|
|||||||
if (options.exportImages) selected.add(3)
|
if (options.exportImages) selected.add(3)
|
||||||
if (options.exportVoices) selected.add(34)
|
if (options.exportVoices) selected.add(34)
|
||||||
if (options.exportVideos) selected.add(43)
|
if (options.exportVideos) selected.add(43)
|
||||||
if (options.exportFiles) selected.add(49)
|
if (options.exportEmojis) selected.add(47)
|
||||||
return selected
|
return selected
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3423,8 +3416,6 @@ class ExportService {
|
|||||||
exportVoices?: boolean
|
exportVoices?: boolean
|
||||||
exportVideos?: boolean
|
exportVideos?: boolean
|
||||||
exportEmojis?: boolean
|
exportEmojis?: boolean
|
||||||
exportFiles?: boolean
|
|
||||||
maxFileSizeMb?: number
|
|
||||||
exportVoiceAsText?: boolean
|
exportVoiceAsText?: boolean
|
||||||
includeVideoPoster?: boolean
|
includeVideoPoster?: boolean
|
||||||
includeVoiceWithTranscript?: boolean
|
includeVoiceWithTranscript?: boolean
|
||||||
@@ -3478,16 +3469,6 @@ class ExportService {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((localType === 49 || localType === 8589934592049) && options.exportFiles && String(msg?.xmlType || '') === '6') {
|
|
||||||
return this.exportFileAttachment(
|
|
||||||
msg,
|
|
||||||
mediaRootDir,
|
|
||||||
mediaRelativePrefix,
|
|
||||||
options.maxFileSizeMb,
|
|
||||||
options.dirCache
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3958,165 +3939,6 @@ class ExportService {
|
|||||||
return tagMatch?.[1]?.toLowerCase()
|
return tagMatch?.[1]?.toLowerCase()
|
||||||
}
|
}
|
||||||
|
|
||||||
private resolveFileAttachmentRoots(): string[] {
|
|
||||||
const dbPath = String(this.configService.get('dbPath') || '').trim()
|
|
||||||
const rawWxid = String(this.configService.get('myWxid') || '').trim()
|
|
||||||
const cleanedWxid = this.cleanAccountDirName(rawWxid)
|
|
||||||
if (!dbPath) return []
|
|
||||||
|
|
||||||
const normalized = dbPath.replace(/[\\/]+$/, '')
|
|
||||||
const roots = new Set<string>()
|
|
||||||
const tryAddRoot = (candidate: string) => {
|
|
||||||
const fileRoot = path.join(candidate, 'msg', 'file')
|
|
||||||
if (fs.existsSync(fileRoot)) {
|
|
||||||
roots.add(fileRoot)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tryAddRoot(normalized)
|
|
||||||
if (rawWxid) tryAddRoot(path.join(normalized, rawWxid))
|
|
||||||
if (cleanedWxid && cleanedWxid !== rawWxid) tryAddRoot(path.join(normalized, cleanedWxid))
|
|
||||||
|
|
||||||
const dbStoragePath =
|
|
||||||
this.resolveDbStoragePathForExport(normalized, cleanedWxid) ||
|
|
||||||
this.resolveDbStoragePathForExport(normalized, rawWxid)
|
|
||||||
if (dbStoragePath) {
|
|
||||||
tryAddRoot(path.dirname(dbStoragePath))
|
|
||||||
}
|
|
||||||
|
|
||||||
return Array.from(roots)
|
|
||||||
}
|
|
||||||
|
|
||||||
private buildPreferredFileYearMonths(createTime?: unknown): string[] {
|
|
||||||
const raw = Number(createTime)
|
|
||||||
if (!Number.isFinite(raw) || raw <= 0) return []
|
|
||||||
const ts = raw > 1e12 ? raw : raw * 1000
|
|
||||||
const date = new Date(ts)
|
|
||||||
if (Number.isNaN(date.getTime())) return []
|
|
||||||
const y = date.getFullYear()
|
|
||||||
const m = String(date.getMonth() + 1).padStart(2, '0')
|
|
||||||
return [`${y}-${m}`]
|
|
||||||
}
|
|
||||||
|
|
||||||
private async verifyFileHash(sourcePath: string, expectedMd5?: string): Promise<boolean> {
|
|
||||||
const normalizedExpected = String(expectedMd5 || '').trim().toLowerCase()
|
|
||||||
if (!normalizedExpected) return true
|
|
||||||
if (!/^[a-f0-9]{32}$/i.test(normalizedExpected)) return true
|
|
||||||
try {
|
|
||||||
const hash = crypto.createHash('md5')
|
|
||||||
await new Promise<void>((resolve, reject) => {
|
|
||||||
const stream = fs.createReadStream(sourcePath)
|
|
||||||
stream.on('data', chunk => hash.update(chunk))
|
|
||||||
stream.on('end', () => resolve())
|
|
||||||
stream.on('error', reject)
|
|
||||||
})
|
|
||||||
return hash.digest('hex').toLowerCase() === normalizedExpected
|
|
||||||
} catch {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async resolveFileAttachmentCandidates(msg: any): Promise<FileExportCandidate[]> {
|
|
||||||
const fileName = String(msg?.fileName || '').trim()
|
|
||||||
if (!fileName) return []
|
|
||||||
|
|
||||||
const roots = this.resolveFileAttachmentRoots()
|
|
||||||
if (roots.length === 0) return []
|
|
||||||
|
|
||||||
const normalizedMd5 = String(msg?.fileMd5 || '').trim().toLowerCase()
|
|
||||||
const preferredMonths = this.buildPreferredFileYearMonths(msg?.createTime)
|
|
||||||
const candidates: FileExportCandidate[] = []
|
|
||||||
const seen = new Set<string>()
|
|
||||||
|
|
||||||
for (const root of roots) {
|
|
||||||
let monthDirs: string[] = []
|
|
||||||
try {
|
|
||||||
monthDirs = fs.readdirSync(root)
|
|
||||||
.filter(entry => /^\d{4}-\d{2}$/.test(entry) && fs.existsSync(path.join(root, entry)))
|
|
||||||
.sort()
|
|
||||||
} catch {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
const orderedMonths = Array.from(new Set([
|
|
||||||
...preferredMonths,
|
|
||||||
...monthDirs.slice().reverse()
|
|
||||||
]))
|
|
||||||
|
|
||||||
for (const month of orderedMonths) {
|
|
||||||
const sourcePath = path.join(root, month, fileName)
|
|
||||||
if (!fs.existsSync(sourcePath)) continue
|
|
||||||
const resolvedPath = path.resolve(sourcePath)
|
|
||||||
if (seen.has(resolvedPath)) continue
|
|
||||||
seen.add(resolvedPath)
|
|
||||||
|
|
||||||
if (normalizedMd5) {
|
|
||||||
const ok = await this.verifyFileHash(resolvedPath, normalizedMd5)
|
|
||||||
if (ok) {
|
|
||||||
candidates.unshift({ sourcePath: resolvedPath, matchedBy: 'md5', yearMonth: month })
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
candidates.push({ sourcePath: resolvedPath, matchedBy: 'name', yearMonth: month })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return candidates
|
|
||||||
}
|
|
||||||
|
|
||||||
private async exportFileAttachment(
|
|
||||||
msg: any,
|
|
||||||
mediaRootDir: string,
|
|
||||||
mediaRelativePrefix: string,
|
|
||||||
maxFileSizeMb?: number,
|
|
||||||
dirCache?: Set<string>
|
|
||||||
): Promise<MediaExportItem | null> {
|
|
||||||
try {
|
|
||||||
const fileNameRaw = String(msg?.fileName || '').trim()
|
|
||||||
if (!fileNameRaw) return null
|
|
||||||
|
|
||||||
const filesDir = path.join(mediaRootDir, mediaRelativePrefix, 'files')
|
|
||||||
if (!dirCache?.has(filesDir)) {
|
|
||||||
await fs.promises.mkdir(filesDir, { recursive: true })
|
|
||||||
dirCache?.add(filesDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
const candidates = await this.resolveFileAttachmentCandidates(msg)
|
|
||||||
if (candidates.length === 0) return null
|
|
||||||
|
|
||||||
const maxBytes = Number.isFinite(maxFileSizeMb)
|
|
||||||
? Math.max(0, Math.floor(Number(maxFileSizeMb) * 1024 * 1024))
|
|
||||||
: 0
|
|
||||||
|
|
||||||
const selected = candidates[0]
|
|
||||||
const stat = await fs.promises.stat(selected.sourcePath)
|
|
||||||
if (!stat.isFile()) return null
|
|
||||||
if (maxBytes > 0 && stat.size > maxBytes) return null
|
|
||||||
|
|
||||||
const normalizedMd5 = String(msg?.fileMd5 || '').trim().toLowerCase()
|
|
||||||
if (normalizedMd5 && selected.matchedBy !== 'md5') {
|
|
||||||
const verified = await this.verifyFileHash(selected.sourcePath, normalizedMd5)
|
|
||||||
if (!verified) return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const safeBaseName = path.basename(fileNameRaw).replace(/[\\/:*?"<>|]/g, '_') || 'file'
|
|
||||||
const messageId = String(msg?.localId || Date.now())
|
|
||||||
const destFileName = `${messageId}_${safeBaseName}`
|
|
||||||
const destPath = path.join(filesDir, destFileName)
|
|
||||||
const copied = await this.copyFileOptimized(selected.sourcePath, destPath)
|
|
||||||
if (!copied.success) return null
|
|
||||||
|
|
||||||
this.noteMediaTelemetry({ doneFiles: 1, bytesWritten: stat.size })
|
|
||||||
return {
|
|
||||||
relativePath: path.posix.join(mediaRelativePrefix, 'files', destFileName),
|
|
||||||
kind: 'file'
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private extractLocationMeta(content: string, localType: number): {
|
private extractLocationMeta(content: string, localType: number): {
|
||||||
locationLat?: number
|
locationLat?: number
|
||||||
locationLng?: number
|
locationLng?: number
|
||||||
@@ -4173,7 +3995,7 @@ class ExportService {
|
|||||||
mediaRelativePrefix: string
|
mediaRelativePrefix: string
|
||||||
} {
|
} {
|
||||||
const exportMediaEnabled = options.exportMedia === true &&
|
const exportMediaEnabled = options.exportMedia === true &&
|
||||||
Boolean(options.exportImages || options.exportVoices || options.exportVideos || options.exportEmojis || options.exportFiles)
|
Boolean(options.exportImages || options.exportVoices || options.exportVideos || options.exportEmojis)
|
||||||
const outputDir = path.dirname(outputPath)
|
const outputDir = path.dirname(outputPath)
|
||||||
const rawWriteLayout = this.configService.get('exportWriteLayout')
|
const rawWriteLayout = this.configService.get('exportWriteLayout')
|
||||||
const writeLayout = rawWriteLayout === 'A' || rawWriteLayout === 'B' || rawWriteLayout === 'C'
|
const writeLayout = rawWriteLayout === 'A' || rawWriteLayout === 'B' || rawWriteLayout === 'C'
|
||||||
@@ -5110,8 +4932,7 @@ class ExportService {
|
|||||||
return (t === 3 && options.exportImages) || // 图片
|
return (t === 3 && options.exportImages) || // 图片
|
||||||
(t === 47 && options.exportEmojis) || // 表情
|
(t === 47 && options.exportEmojis) || // 表情
|
||||||
(t === 43 && options.exportVideos) || // 视频
|
(t === 43 && options.exportVideos) || // 视频
|
||||||
(t === 34 && options.exportVoices) || // 语音文件
|
(t === 34 && options.exportVoices) // 语音文件
|
||||||
((t === 49 || t === 8589934592049) && options.exportFiles && String(msg?.xmlType || '') === '6')
|
|
||||||
})
|
})
|
||||||
: []
|
: []
|
||||||
|
|
||||||
@@ -5152,8 +4973,6 @@ class ExportService {
|
|||||||
exportVoices: options.exportVoices,
|
exportVoices: options.exportVoices,
|
||||||
exportVideos: options.exportVideos,
|
exportVideos: options.exportVideos,
|
||||||
exportEmojis: options.exportEmojis,
|
exportEmojis: options.exportEmojis,
|
||||||
exportFiles: options.exportFiles,
|
|
||||||
maxFileSizeMb: options.maxFileSizeMb,
|
|
||||||
exportVoiceAsText: options.exportVoiceAsText,
|
exportVoiceAsText: options.exportVoiceAsText,
|
||||||
includeVideoPoster: options.format === 'html',
|
includeVideoPoster: options.format === 'html',
|
||||||
imageDeepSearchOnMiss: options.imageDeepSearchOnMiss,
|
imageDeepSearchOnMiss: options.imageDeepSearchOnMiss,
|
||||||
@@ -5622,8 +5441,7 @@ class ExportService {
|
|||||||
return (t === 3 && options.exportImages) ||
|
return (t === 3 && options.exportImages) ||
|
||||||
(t === 47 && options.exportEmojis) ||
|
(t === 47 && options.exportEmojis) ||
|
||||||
(t === 43 && options.exportVideos) ||
|
(t === 43 && options.exportVideos) ||
|
||||||
(t === 34 && options.exportVoices) ||
|
(t === 34 && options.exportVoices)
|
||||||
((t === 49 || t === 8589934592049) && options.exportFiles && String(msg?.xmlType || '') === '6')
|
|
||||||
})
|
})
|
||||||
: []
|
: []
|
||||||
|
|
||||||
@@ -5663,8 +5481,6 @@ class ExportService {
|
|||||||
exportVoices: options.exportVoices,
|
exportVoices: options.exportVoices,
|
||||||
exportVideos: options.exportVideos,
|
exportVideos: options.exportVideos,
|
||||||
exportEmojis: options.exportEmojis,
|
exportEmojis: options.exportEmojis,
|
||||||
exportFiles: options.exportFiles,
|
|
||||||
maxFileSizeMb: options.maxFileSizeMb,
|
|
||||||
exportVoiceAsText: options.exportVoiceAsText,
|
exportVoiceAsText: options.exportVoiceAsText,
|
||||||
includeVideoPoster: options.format === 'html',
|
includeVideoPoster: options.format === 'html',
|
||||||
imageDeepSearchOnMiss: options.imageDeepSearchOnMiss,
|
imageDeepSearchOnMiss: options.imageDeepSearchOnMiss,
|
||||||
@@ -6485,8 +6301,7 @@ class ExportService {
|
|||||||
return (t === 3 && options.exportImages) ||
|
return (t === 3 && options.exportImages) ||
|
||||||
(t === 47 && options.exportEmojis) ||
|
(t === 47 && options.exportEmojis) ||
|
||||||
(t === 43 && options.exportVideos) ||
|
(t === 43 && options.exportVideos) ||
|
||||||
(t === 34 && options.exportVoices) ||
|
(t === 34 && options.exportVoices)
|
||||||
((t === 49 || t === 8589934592049) && options.exportFiles && String(msg?.xmlType || '') === '6')
|
|
||||||
})
|
})
|
||||||
: []
|
: []
|
||||||
|
|
||||||
@@ -6526,8 +6341,6 @@ class ExportService {
|
|||||||
exportVoices: options.exportVoices,
|
exportVoices: options.exportVoices,
|
||||||
exportVideos: options.exportVideos,
|
exportVideos: options.exportVideos,
|
||||||
exportEmojis: options.exportEmojis,
|
exportEmojis: options.exportEmojis,
|
||||||
exportFiles: options.exportFiles,
|
|
||||||
maxFileSizeMb: options.maxFileSizeMb,
|
|
||||||
exportVoiceAsText: options.exportVoiceAsText,
|
exportVoiceAsText: options.exportVoiceAsText,
|
||||||
includeVideoPoster: options.format === 'html',
|
includeVideoPoster: options.format === 'html',
|
||||||
imageDeepSearchOnMiss: options.imageDeepSearchOnMiss,
|
imageDeepSearchOnMiss: options.imageDeepSearchOnMiss,
|
||||||
@@ -7201,8 +7014,7 @@ class ExportService {
|
|||||||
return (t === 3 && options.exportImages) ||
|
return (t === 3 && options.exportImages) ||
|
||||||
(t === 47 && options.exportEmojis) ||
|
(t === 47 && options.exportEmojis) ||
|
||||||
(t === 43 && options.exportVideos) ||
|
(t === 43 && options.exportVideos) ||
|
||||||
(t === 34 && options.exportVoices) ||
|
(t === 34 && options.exportVoices)
|
||||||
((t === 49 || t === 8589934592049) && options.exportFiles && String(msg?.xmlType || '') === '6')
|
|
||||||
})
|
})
|
||||||
: []
|
: []
|
||||||
|
|
||||||
@@ -7242,8 +7054,6 @@ class ExportService {
|
|||||||
exportVoices: options.exportVoices,
|
exportVoices: options.exportVoices,
|
||||||
exportVideos: options.exportVideos,
|
exportVideos: options.exportVideos,
|
||||||
exportEmojis: options.exportEmojis,
|
exportEmojis: options.exportEmojis,
|
||||||
exportFiles: options.exportFiles,
|
|
||||||
maxFileSizeMb: options.maxFileSizeMb,
|
|
||||||
exportVoiceAsText: options.exportVoiceAsText,
|
exportVoiceAsText: options.exportVoiceAsText,
|
||||||
includeVideoPoster: options.format === 'html',
|
includeVideoPoster: options.format === 'html',
|
||||||
imageDeepSearchOnMiss: options.imageDeepSearchOnMiss,
|
imageDeepSearchOnMiss: options.imageDeepSearchOnMiss,
|
||||||
@@ -7581,8 +7391,7 @@ class ExportService {
|
|||||||
return (t === 3 && options.exportImages) ||
|
return (t === 3 && options.exportImages) ||
|
||||||
(t === 47 && options.exportEmojis) ||
|
(t === 47 && options.exportEmojis) ||
|
||||||
(t === 43 && options.exportVideos) ||
|
(t === 43 && options.exportVideos) ||
|
||||||
(t === 34 && options.exportVoices) ||
|
(t === 34 && options.exportVoices)
|
||||||
((t === 49 || t === 8589934592049) && options.exportFiles && String(msg?.xmlType || '') === '6')
|
|
||||||
})
|
})
|
||||||
: []
|
: []
|
||||||
|
|
||||||
@@ -7622,8 +7431,6 @@ class ExportService {
|
|||||||
exportVoices: options.exportVoices,
|
exportVoices: options.exportVoices,
|
||||||
exportVideos: options.exportVideos,
|
exportVideos: options.exportVideos,
|
||||||
exportEmojis: options.exportEmojis,
|
exportEmojis: options.exportEmojis,
|
||||||
exportFiles: options.exportFiles,
|
|
||||||
maxFileSizeMb: options.maxFileSizeMb,
|
|
||||||
exportVoiceAsText: options.exportVoiceAsText,
|
exportVoiceAsText: options.exportVoiceAsText,
|
||||||
includeVideoPoster: options.format === 'html',
|
includeVideoPoster: options.format === 'html',
|
||||||
imageDeepSearchOnMiss: options.imageDeepSearchOnMiss,
|
imageDeepSearchOnMiss: options.imageDeepSearchOnMiss,
|
||||||
@@ -8044,8 +7851,6 @@ class ExportService {
|
|||||||
exportImages: options.exportImages,
|
exportImages: options.exportImages,
|
||||||
exportVoices: options.exportVoices,
|
exportVoices: options.exportVoices,
|
||||||
exportEmojis: options.exportEmojis,
|
exportEmojis: options.exportEmojis,
|
||||||
exportFiles: options.exportFiles,
|
|
||||||
maxFileSizeMb: options.maxFileSizeMb,
|
|
||||||
exportVoiceAsText: options.exportVoiceAsText,
|
exportVoiceAsText: options.exportVoiceAsText,
|
||||||
includeVideoPoster: options.format === 'html',
|
includeVideoPoster: options.format === 'html',
|
||||||
includeVoiceWithTranscript: true,
|
includeVoiceWithTranscript: true,
|
||||||
|
|||||||
56
package-lock.json
generated
56
package-lock.json
generated
@@ -27,7 +27,7 @@
|
|||||||
"react-router-dom": "^7.14.0",
|
"react-router-dom": "^7.14.0",
|
||||||
"react-virtuoso": "^4.18.1",
|
"react-virtuoso": "^4.18.1",
|
||||||
"remark-gfm": "^4.0.1",
|
"remark-gfm": "^4.0.1",
|
||||||
"sherpa-onnx-node": "^1.10.38",
|
"sherpa-onnx-node": "^1.12.35",
|
||||||
"silk-wasm": "^3.7.1",
|
"silk-wasm": "^3.7.1",
|
||||||
"sudo-prompt": "^9.2.1",
|
"sudo-prompt": "^9.2.1",
|
||||||
"wechat-emojis": "^1.0.2",
|
"wechat-emojis": "^1.0.2",
|
||||||
@@ -9087,9 +9087,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/sherpa-onnx-darwin-arm64": {
|
"node_modules/sherpa-onnx-darwin-arm64": {
|
||||||
"version": "1.12.34",
|
"version": "1.12.35",
|
||||||
"resolved": "https://registry.npmjs.org/sherpa-onnx-darwin-arm64/-/sherpa-onnx-darwin-arm64-1.12.34.tgz",
|
"resolved": "https://registry.npmjs.org/sherpa-onnx-darwin-arm64/-/sherpa-onnx-darwin-arm64-1.12.35.tgz",
|
||||||
"integrity": "sha512-UMUZW+NAto+Na7wOYzAwwPU7wZtWdkYcoTNQ5RgDPkPW6PO6l+AlaUxoJJR6ehNojoEAfSxSOpQz+GYkDTHgJw==",
|
"integrity": "sha512-WGIABo3ruBXE/7FhAdaVNuM+ZKx0B7jkA+jT22k5TxUcw58nWzgkY6k+CPdM14lfaaXR+jPWdDrM4gXl/bP4RQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -9100,9 +9100,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/sherpa-onnx-darwin-x64": {
|
"node_modules/sherpa-onnx-darwin-x64": {
|
||||||
"version": "1.12.34",
|
"version": "1.12.35",
|
||||||
"resolved": "https://registry.npmjs.org/sherpa-onnx-darwin-x64/-/sherpa-onnx-darwin-x64-1.12.34.tgz",
|
"resolved": "https://registry.npmjs.org/sherpa-onnx-darwin-x64/-/sherpa-onnx-darwin-x64-1.12.35.tgz",
|
||||||
"integrity": "sha512-ni9nAkceaUM7X7OglnipiHhFd0XDN6OaQdOBfR7ePVWIj0FOfJgZsHbFeBK8g3erd2Q1O07isOiidMd1rslTJg==",
|
"integrity": "sha512-hzWQm4CJhGyf3N9Sd1Oobcdz49FauuSCmhrm5vRqydyNsANjs89wATHAuatPAtinpBkgEqacDPrGz+1A/BWpNA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -9113,9 +9113,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/sherpa-onnx-linux-arm64": {
|
"node_modules/sherpa-onnx-linux-arm64": {
|
||||||
"version": "1.12.34",
|
"version": "1.12.35",
|
||||||
"resolved": "https://registry.npmjs.org/sherpa-onnx-linux-arm64/-/sherpa-onnx-linux-arm64-1.12.34.tgz",
|
"resolved": "https://registry.npmjs.org/sherpa-onnx-linux-arm64/-/sherpa-onnx-linux-arm64-1.12.35.tgz",
|
||||||
"integrity": "sha512-0w6x9onElqmDYoIm7+gLHIbNzCZ6+ivKBMkrSMI1iTNVtSV0jLumY5XwW9VgzNeEfnLCK7eqlviMKQPo7M52UA==",
|
"integrity": "sha512-9glJ+dRv/rFWz/61tiKfaR9Gj+8B6sXi7NBgwBAnO/+ygu/WAjBfQRz2+S0YIy1dxqu7ng246TBNnx1M2XaNXA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -9126,9 +9126,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/sherpa-onnx-linux-x64": {
|
"node_modules/sherpa-onnx-linux-x64": {
|
||||||
"version": "1.12.34",
|
"version": "1.12.35",
|
||||||
"resolved": "https://registry.npmjs.org/sherpa-onnx-linux-x64/-/sherpa-onnx-linux-x64-1.12.34.tgz",
|
"resolved": "https://registry.npmjs.org/sherpa-onnx-linux-x64/-/sherpa-onnx-linux-x64-1.12.35.tgz",
|
||||||
"integrity": "sha512-yIf3A+F/hUwPX/YJ0XSaB+KoS4a+sQa3qdQ1Bai046yfCxCRLC8+mDFnSVPf/Ekp3U3jhKLRv4F+68ZXrV2qHw==",
|
"integrity": "sha512-h+v4Yed8T+k1qLlKX2LTGoXP/11ycz7jbqC2f80kDWgz9J8m46mOBa/H20wVkLyQPy1vG1O5iH5Fe5Wh4QlLhw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -9139,23 +9139,23 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/sherpa-onnx-node": {
|
"node_modules/sherpa-onnx-node": {
|
||||||
"version": "1.12.34",
|
"version": "1.12.35",
|
||||||
"resolved": "https://registry.npmjs.org/sherpa-onnx-node/-/sherpa-onnx-node-1.12.34.tgz",
|
"resolved": "https://registry.npmjs.org/sherpa-onnx-node/-/sherpa-onnx-node-1.12.35.tgz",
|
||||||
"integrity": "sha512-Ov3nqqSJBiW45KMfV32smo3NNqYO1oiB9nUR7sbRpRunoZZZrxbFg8YkH+pZ8VlcErDyJVSLk/oKtqwHGc13lQ==",
|
"integrity": "sha512-RHCgV+9fos/ZxP0MsIL7JPU9K3YHnIDmwtX674ChQZY6DLVaIQaju+J3hDqzRu1R3agnDg9WDf01zsT46NC7SQ==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"sherpa-onnx-darwin-arm64": "^1.12.34",
|
"sherpa-onnx-darwin-arm64": "^1.12.35",
|
||||||
"sherpa-onnx-darwin-x64": "^1.12.34",
|
"sherpa-onnx-darwin-x64": "^1.12.35",
|
||||||
"sherpa-onnx-linux-arm64": "^1.12.34",
|
"sherpa-onnx-linux-arm64": "^1.12.35",
|
||||||
"sherpa-onnx-linux-x64": "^1.12.34",
|
"sherpa-onnx-linux-x64": "^1.12.35",
|
||||||
"sherpa-onnx-win-ia32": "^1.12.34",
|
"sherpa-onnx-win-ia32": "^1.12.35",
|
||||||
"sherpa-onnx-win-x64": "^1.12.34"
|
"sherpa-onnx-win-x64": "^1.12.35"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/sherpa-onnx-win-ia32": {
|
"node_modules/sherpa-onnx-win-ia32": {
|
||||||
"version": "1.12.34",
|
"version": "1.12.35",
|
||||||
"resolved": "https://registry.npmjs.org/sherpa-onnx-win-ia32/-/sherpa-onnx-win-ia32-1.12.34.tgz",
|
"resolved": "https://registry.npmjs.org/sherpa-onnx-win-ia32/-/sherpa-onnx-win-ia32-1.12.35.tgz",
|
||||||
"integrity": "sha512-AAhK2dvx1zSYLae7NTmxnXmD8bTWHcd1Rr1MQRnDAAGAFW0rnZ7WSmJwsoZ4uT2K+d4Kf4vlbSxl8k8qzWkq6g==",
|
"integrity": "sha512-6H6BSdXXWtz92AuvOmr4w/QvCofxXbfbNKT7jCxdE7Nd4AvinLJxT02vbnL6T54vuXd9chu0QvQrDl1tuRphAA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@@ -9166,9 +9166,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/sherpa-onnx-win-x64": {
|
"node_modules/sherpa-onnx-win-x64": {
|
||||||
"version": "1.12.34",
|
"version": "1.12.35",
|
||||||
"resolved": "https://registry.npmjs.org/sherpa-onnx-win-x64/-/sherpa-onnx-win-x64-1.12.34.tgz",
|
"resolved": "https://registry.npmjs.org/sherpa-onnx-win-x64/-/sherpa-onnx-win-x64-1.12.35.tgz",
|
||||||
"integrity": "sha512-OjQwOfoKIKL1F/i1hjV8918FYZFVwHxrSnk4/yvG1GLzabzifzGcKcj5SjGnIJSH3Zj233wZStTLTrBH+8+BfA==",
|
"integrity": "sha512-+GLrxwaEvpJAO0KZgKulfd4qUR089MD+TjE5jVSugMTq4Eh/R/TpPPqYQGibRZVPHW7Se1ABfHGapZQoFMHH5Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
"react-router-dom": "^7.14.0",
|
"react-router-dom": "^7.14.0",
|
||||||
"react-virtuoso": "^4.18.1",
|
"react-virtuoso": "^4.18.1",
|
||||||
"remark-gfm": "^4.0.1",
|
"remark-gfm": "^4.0.1",
|
||||||
"sherpa-onnx-node": "^1.10.38",
|
"sherpa-onnx-node": "^1.12.35",
|
||||||
"silk-wasm": "^3.7.1",
|
"silk-wasm": "^3.7.1",
|
||||||
"sudo-prompt": "^9.2.1",
|
"sudo-prompt": "^9.2.1",
|
||||||
"wechat-emojis": "^1.0.2",
|
"wechat-emojis": "^1.0.2",
|
||||||
|
|||||||
50
src/App.tsx
50
src/App.tsx
@@ -591,13 +591,9 @@ function App() {
|
|||||||
<div className="agreement-notice">
|
<div className="agreement-notice">
|
||||||
<strong>这是免费软件,如果你是付费购买的话请骂死那个骗子。</strong>
|
<strong>这是免费软件,如果你是付费购买的话请骂死那个骗子。</strong>
|
||||||
<span className="agreement-notice-link">
|
<span className="agreement-notice-link">
|
||||||
官方网站:
|
我们唯一的官方网站:
|
||||||
<a href="https://weflow.top" target="_blank" rel="noreferrer">
|
|
||||||
https://weflow.top
|
|
||||||
</a>
|
|
||||||
·
|
|
||||||
<a href="https://github.com/hicccc77/WeFlow" target="_blank" rel="noreferrer">
|
<a href="https://github.com/hicccc77/WeFlow" target="_blank" rel="noreferrer">
|
||||||
GitHub 仓库
|
https://github.com/hicccc77/WeFlow
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -612,7 +608,7 @@ function App() {
|
|||||||
<p>因使用本软件产生的任何直接或间接损失,开发者不承担任何责任。请确保你的使用行为符合当地法律法规。</p>
|
<p>因使用本软件产生的任何直接或间接损失,开发者不承担任何责任。请确保你的使用行为符合当地法律法规。</p>
|
||||||
|
|
||||||
<h4>4. 隐私保护</h4>
|
<h4>4. 隐私保护</h4>
|
||||||
<p>本软件不收集任何用户隐私数据。软件更新检测仅获取版本信息,不涉及任何个人隐私。</p>
|
<p>本软件不收集任何用户数据。软件更新检测仅获取版本信息,不涉及任何个人隐私。</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="agreement-footer">
|
<div className="agreement-footer">
|
||||||
@@ -670,30 +666,30 @@ function App() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{showWaylandWarning && (
|
{showWaylandWarning && (
|
||||||
<div className="agreement-overlay">
|
<div className="agreement-overlay">
|
||||||
<div className="agreement-modal">
|
<div className="agreement-modal">
|
||||||
<div className="agreement-header">
|
<div className="agreement-header">
|
||||||
<Shield size={32} />
|
<Shield size={32} />
|
||||||
<h2>环境兼容性提示 (Wayland)</h2>
|
<h2>环境兼容性提示 (Wayland)</h2>
|
||||||
</div>
|
|
||||||
<div className="agreement-content">
|
|
||||||
<div className="agreement-text">
|
|
||||||
<p>检测到您当前正在使用 <strong>Wayland</strong> 显示服务器。</p>
|
|
||||||
<p>在 Wayland 环境下,出于系统级的安全与设计机制,<strong>应用程序无法直接控制新弹出窗口的位置</strong>。</p>
|
|
||||||
<p>这可能导致某些独立窗口(如消息通知、图片查看器等)出现位置随机、或不受控制的情况。这是底层机制导致的,对此我们无能为力。</p>
|
|
||||||
<br />
|
|
||||||
<p>如果您觉得窗口位置异常严重影响了使用体验,建议尝试:</p>
|
|
||||||
<p>1. 在系统登录界面,将会话切换回 <strong>X11 (Xorg)</strong> 模式。</p>
|
|
||||||
<p>2. 修改您的桌面管理器 (WM/DE) 配置,强制指定该应用程序的窗口规则。</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="agreement-content">
|
||||||
<div className="agreement-footer">
|
<div className="agreement-text">
|
||||||
<div className="agreement-actions">
|
<p>检测到您当前正在使用 <strong>Wayland</strong> 显示服务器。</p>
|
||||||
<button className="btn btn-primary" onClick={handleDismissWaylandWarning}>我知道了,不再提示</button>
|
<p>在 Wayland 环境下,出于系统级的安全与设计机制,<strong>应用程序无法直接控制新弹出窗口的位置</strong>。</p>
|
||||||
|
<p>这可能导致某些独立窗口(如消息通知、图片查看器等)出现位置随机、或不受控制的情况。这是底层机制导致的,对此我们无能为力。</p>
|
||||||
|
<br />
|
||||||
|
<p>如果您觉得窗口位置异常严重影响了使用体验,建议尝试:</p>
|
||||||
|
<p>1. 在系统登录界面,将会话切换回 <strong>X11 (Xorg)</strong> 模式。</p>
|
||||||
|
<p>2. 修改您的桌面管理器 (WM/DE) 配置,强制指定该应用程序的窗口规则。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="agreement-footer">
|
||||||
|
<div className="agreement-actions">
|
||||||
|
<button className="btn btn-primary" onClick={handleDismissWaylandWarning}>我知道了,不再提示</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* 更新提示对话框 */}
|
{/* 更新提示对话框 */}
|
||||||
|
|||||||
@@ -66,8 +66,7 @@ export function ExportDefaultsSettingsForm({
|
|||||||
images: true,
|
images: true,
|
||||||
videos: true,
|
videos: true,
|
||||||
voices: true,
|
voices: true,
|
||||||
emojis: true,
|
emojis: true
|
||||||
files: true
|
|
||||||
})
|
})
|
||||||
const [exportDefaultVoiceAsText, setExportDefaultVoiceAsText] = useState(false)
|
const [exportDefaultVoiceAsText, setExportDefaultVoiceAsText] = useState(false)
|
||||||
const [exportDefaultExcelCompactColumns, setExportDefaultExcelCompactColumns] = useState(true)
|
const [exportDefaultExcelCompactColumns, setExportDefaultExcelCompactColumns] = useState(true)
|
||||||
@@ -95,8 +94,7 @@ export function ExportDefaultsSettingsForm({
|
|||||||
images: true,
|
images: true,
|
||||||
videos: true,
|
videos: true,
|
||||||
voices: true,
|
voices: true,
|
||||||
emojis: true,
|
emojis: true
|
||||||
files: true
|
|
||||||
})
|
})
|
||||||
setExportDefaultVoiceAsText(savedVoiceAsText ?? false)
|
setExportDefaultVoiceAsText(savedVoiceAsText ?? false)
|
||||||
setExportDefaultExcelCompactColumns(savedExcelCompactColumns ?? true)
|
setExportDefaultExcelCompactColumns(savedExcelCompactColumns ?? true)
|
||||||
@@ -294,7 +292,7 @@ export function ExportDefaultsSettingsForm({
|
|||||||
<div className="form-group media-setting-group">
|
<div className="form-group media-setting-group">
|
||||||
<div className="form-copy">
|
<div className="form-copy">
|
||||||
<label>默认导出媒体内容</label>
|
<label>默认导出媒体内容</label>
|
||||||
<span className="form-hint">控制图片、视频、语音、表情包、文件的默认导出开关</span>
|
<span className="form-hint">控制图片、视频、语音、表情包的默认导出开关</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-control">
|
<div className="form-control">
|
||||||
<div className="media-default-grid">
|
<div className="media-default-grid">
|
||||||
@@ -354,20 +352,6 @@ export function ExportDefaultsSettingsForm({
|
|||||||
/>
|
/>
|
||||||
表情包
|
表情包
|
||||||
</label>
|
</label>
|
||||||
<label>
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
checked={exportDefaultMedia.files}
|
|
||||||
onChange={async (e) => {
|
|
||||||
const next = { ...exportDefaultMedia, files: e.target.checked }
|
|
||||||
setExportDefaultMedia(next)
|
|
||||||
await configService.setExportDefaultMedia(next)
|
|
||||||
onDefaultsChanged?.({ media: next })
|
|
||||||
notify(`已${e.target.checked ? '开启' : '关闭'}默认导出文件`, true)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
文件
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ import './ExportPage.scss'
|
|||||||
type ConversationTab = 'private' | 'group' | 'official' | 'former_friend'
|
type ConversationTab = 'private' | 'group' | 'official' | 'former_friend'
|
||||||
type TaskStatus = 'queued' | 'running' | 'success' | 'error'
|
type TaskStatus = 'queued' | 'running' | 'success' | 'error'
|
||||||
type TaskScope = 'single' | 'multi' | 'content' | 'sns'
|
type TaskScope = 'single' | 'multi' | 'content' | 'sns'
|
||||||
type ContentType = 'text' | 'voice' | 'image' | 'video' | 'emoji' | 'file'
|
type ContentType = 'text' | 'voice' | 'image' | 'video' | 'emoji'
|
||||||
type ContentCardType = ContentType | 'sns'
|
type ContentCardType = ContentType | 'sns'
|
||||||
type SnsRankMode = 'likes' | 'comments'
|
type SnsRankMode = 'likes' | 'comments'
|
||||||
|
|
||||||
@@ -88,8 +88,6 @@ interface ExportOptions {
|
|||||||
exportVoices: boolean
|
exportVoices: boolean
|
||||||
exportVideos: boolean
|
exportVideos: boolean
|
||||||
exportEmojis: boolean
|
exportEmojis: boolean
|
||||||
exportFiles: boolean
|
|
||||||
maxFileSizeMb: number
|
|
||||||
exportVoiceAsText: boolean
|
exportVoiceAsText: boolean
|
||||||
excelCompactColumns: boolean
|
excelCompactColumns: boolean
|
||||||
txtColumns: string[]
|
txtColumns: string[]
|
||||||
@@ -197,8 +195,7 @@ const contentTypeLabels: Record<ContentType, string> = {
|
|||||||
voice: '语音',
|
voice: '语音',
|
||||||
image: '图片',
|
image: '图片',
|
||||||
video: '视频',
|
video: '视频',
|
||||||
emoji: '表情包',
|
emoji: '表情包'
|
||||||
file: '文件'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const backgroundTaskSourceLabels: Record<string, string> = {
|
const backgroundTaskSourceLabels: Record<string, string> = {
|
||||||
@@ -1601,8 +1598,7 @@ function ExportPage() {
|
|||||||
images: true,
|
images: true,
|
||||||
videos: true,
|
videos: true,
|
||||||
voices: true,
|
voices: true,
|
||||||
emojis: true,
|
emojis: true
|
||||||
files: true
|
|
||||||
})
|
})
|
||||||
const [exportDefaultVoiceAsText, setExportDefaultVoiceAsText] = useState(false)
|
const [exportDefaultVoiceAsText, setExportDefaultVoiceAsText] = useState(false)
|
||||||
const [exportDefaultExcelCompactColumns, setExportDefaultExcelCompactColumns] = useState(true)
|
const [exportDefaultExcelCompactColumns, setExportDefaultExcelCompactColumns] = useState(true)
|
||||||
@@ -1621,9 +1617,7 @@ function ExportPage() {
|
|||||||
exportImages: true,
|
exportImages: true,
|
||||||
exportVoices: true,
|
exportVoices: true,
|
||||||
exportVideos: true,
|
exportVideos: true,
|
||||||
exportEmojis: true,
|
exportEmojis: true,
|
||||||
exportFiles: true,
|
|
||||||
maxFileSizeMb: 200,
|
|
||||||
exportVoiceAsText: false,
|
exportVoiceAsText: false,
|
||||||
excelCompactColumns: true,
|
excelCompactColumns: true,
|
||||||
txtColumns: defaultTxtColumns,
|
txtColumns: defaultTxtColumns,
|
||||||
@@ -2287,8 +2281,7 @@ function ExportPage() {
|
|||||||
images: true,
|
images: true,
|
||||||
videos: true,
|
videos: true,
|
||||||
voices: true,
|
voices: true,
|
||||||
emojis: true,
|
emojis: true
|
||||||
files: true
|
|
||||||
})
|
})
|
||||||
setExportDefaultVoiceAsText(savedVoiceAsText ?? false)
|
setExportDefaultVoiceAsText(savedVoiceAsText ?? false)
|
||||||
setExportDefaultExcelCompactColumns(savedExcelCompactColumns ?? true)
|
setExportDefaultExcelCompactColumns(savedExcelCompactColumns ?? true)
|
||||||
@@ -2317,14 +2310,12 @@ function ExportPage() {
|
|||||||
(savedMedia?.images ?? prev.exportImages) ||
|
(savedMedia?.images ?? prev.exportImages) ||
|
||||||
(savedMedia?.voices ?? prev.exportVoices) ||
|
(savedMedia?.voices ?? prev.exportVoices) ||
|
||||||
(savedMedia?.videos ?? prev.exportVideos) ||
|
(savedMedia?.videos ?? prev.exportVideos) ||
|
||||||
(savedMedia?.emojis ?? prev.exportEmojis) ||
|
(savedMedia?.emojis ?? prev.exportEmojis)
|
||||||
(savedMedia?.files ?? prev.exportFiles)
|
|
||||||
),
|
),
|
||||||
exportImages: savedMedia?.images ?? prev.exportImages,
|
exportImages: savedMedia?.images ?? prev.exportImages,
|
||||||
exportVoices: savedMedia?.voices ?? prev.exportVoices,
|
exportVoices: savedMedia?.voices ?? prev.exportVoices,
|
||||||
exportVideos: savedMedia?.videos ?? prev.exportVideos,
|
exportVideos: savedMedia?.videos ?? prev.exportVideos,
|
||||||
exportEmojis: savedMedia?.emojis ?? prev.exportEmojis,
|
exportEmojis: savedMedia?.emojis ?? prev.exportEmojis,
|
||||||
exportFiles: savedMedia?.files ?? prev.exportFiles,
|
|
||||||
exportVoiceAsText: savedVoiceAsText ?? prev.exportVoiceAsText,
|
exportVoiceAsText: savedVoiceAsText ?? prev.exportVoiceAsText,
|
||||||
excelCompactColumns: savedExcelCompactColumns ?? prev.excelCompactColumns,
|
excelCompactColumns: savedExcelCompactColumns ?? prev.excelCompactColumns,
|
||||||
txtColumns,
|
txtColumns,
|
||||||
@@ -4097,15 +4088,12 @@ function ExportPage() {
|
|||||||
exportDefaultMedia.images ||
|
exportDefaultMedia.images ||
|
||||||
exportDefaultMedia.voices ||
|
exportDefaultMedia.voices ||
|
||||||
exportDefaultMedia.videos ||
|
exportDefaultMedia.videos ||
|
||||||
exportDefaultMedia.emojis ||
|
exportDefaultMedia.emojis
|
||||||
exportDefaultMedia.files
|
|
||||||
),
|
),
|
||||||
exportImages: exportDefaultMedia.images,
|
exportImages: exportDefaultMedia.images,
|
||||||
exportVoices: exportDefaultMedia.voices,
|
exportVoices: exportDefaultMedia.voices,
|
||||||
exportVideos: exportDefaultMedia.videos,
|
exportVideos: exportDefaultMedia.videos,
|
||||||
exportEmojis: exportDefaultMedia.emojis,
|
exportEmojis: exportDefaultMedia.emojis,
|
||||||
exportFiles: exportDefaultMedia.files,
|
|
||||||
maxFileSizeMb: prev.maxFileSizeMb,
|
|
||||||
exportVoiceAsText: exportDefaultVoiceAsText,
|
exportVoiceAsText: exportDefaultVoiceAsText,
|
||||||
excelCompactColumns: exportDefaultExcelCompactColumns,
|
excelCompactColumns: exportDefaultExcelCompactColumns,
|
||||||
exportConcurrency: exportDefaultConcurrency,
|
exportConcurrency: exportDefaultConcurrency,
|
||||||
@@ -4123,14 +4111,12 @@ function ExportPage() {
|
|||||||
next.exportVoices = false
|
next.exportVoices = false
|
||||||
next.exportVideos = false
|
next.exportVideos = false
|
||||||
next.exportEmojis = false
|
next.exportEmojis = false
|
||||||
next.exportFiles = false
|
|
||||||
} else {
|
} else {
|
||||||
next.exportMedia = true
|
next.exportMedia = true
|
||||||
next.exportImages = payload.contentType === 'image'
|
next.exportImages = payload.contentType === 'image'
|
||||||
next.exportVoices = payload.contentType === 'voice'
|
next.exportVoices = payload.contentType === 'voice'
|
||||||
next.exportVideos = payload.contentType === 'video'
|
next.exportVideos = payload.contentType === 'video'
|
||||||
next.exportEmojis = payload.contentType === 'emoji'
|
next.exportEmojis = payload.contentType === 'emoji'
|
||||||
next.exportFiles = payload.contentType === 'file'
|
|
||||||
next.exportVoiceAsText = false
|
next.exportVoiceAsText = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4349,13 +4335,7 @@ function ExportPage() {
|
|||||||
|
|
||||||
const buildExportOptions = (scope: TaskScope, contentType?: ContentType): ElectronExportOptions => {
|
const buildExportOptions = (scope: TaskScope, contentType?: ContentType): ElectronExportOptions => {
|
||||||
const sessionLayout: SessionLayout = writeLayout === 'C' ? 'per-session' : 'shared'
|
const sessionLayout: SessionLayout = writeLayout === 'C' ? 'per-session' : 'shared'
|
||||||
const exportMediaEnabled = Boolean(
|
const exportMediaEnabled = Boolean(options.exportImages || options.exportVoices || options.exportVideos || options.exportEmojis)
|
||||||
options.exportImages ||
|
|
||||||
options.exportVoices ||
|
|
||||||
options.exportVideos ||
|
|
||||||
options.exportEmojis ||
|
|
||||||
options.exportFiles
|
|
||||||
)
|
|
||||||
|
|
||||||
const base: ElectronExportOptions = {
|
const base: ElectronExportOptions = {
|
||||||
format: options.format,
|
format: options.format,
|
||||||
@@ -4365,8 +4345,6 @@ function ExportPage() {
|
|||||||
exportVoices: options.exportVoices,
|
exportVoices: options.exportVoices,
|
||||||
exportVideos: options.exportVideos,
|
exportVideos: options.exportVideos,
|
||||||
exportEmojis: options.exportEmojis,
|
exportEmojis: options.exportEmojis,
|
||||||
exportFiles: options.exportFiles,
|
|
||||||
maxFileSizeMb: options.maxFileSizeMb,
|
|
||||||
exportVoiceAsText: options.exportVoiceAsText,
|
exportVoiceAsText: options.exportVoiceAsText,
|
||||||
excelCompactColumns: options.excelCompactColumns,
|
excelCompactColumns: options.excelCompactColumns,
|
||||||
txtColumns: options.txtColumns,
|
txtColumns: options.txtColumns,
|
||||||
@@ -4397,8 +4375,7 @@ function ExportPage() {
|
|||||||
exportImages: false,
|
exportImages: false,
|
||||||
exportVoices: false,
|
exportVoices: false,
|
||||||
exportVideos: false,
|
exportVideos: false,
|
||||||
exportEmojis: false,
|
exportEmojis: false
|
||||||
exportFiles: false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4410,7 +4387,6 @@ function ExportPage() {
|
|||||||
exportVoices: contentType === 'voice',
|
exportVoices: contentType === 'voice',
|
||||||
exportVideos: contentType === 'video',
|
exportVideos: contentType === 'video',
|
||||||
exportEmojis: contentType === 'emoji',
|
exportEmojis: contentType === 'emoji',
|
||||||
exportFiles: contentType === 'file',
|
|
||||||
exportVoiceAsText: false
|
exportVoiceAsText: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4476,7 +4452,6 @@ function ExportPage() {
|
|||||||
if (opts.exportVoices) labels.push('语音')
|
if (opts.exportVoices) labels.push('语音')
|
||||||
if (opts.exportVideos) labels.push('视频')
|
if (opts.exportVideos) labels.push('视频')
|
||||||
if (opts.exportEmojis) labels.push('表情包')
|
if (opts.exportEmojis) labels.push('表情包')
|
||||||
if (opts.exportFiles) labels.push('文件')
|
|
||||||
}
|
}
|
||||||
return Array.from(new Set(labels)).join('、')
|
return Array.from(new Set(labels)).join('、')
|
||||||
}, [])
|
}, [])
|
||||||
@@ -4532,7 +4507,6 @@ function ExportPage() {
|
|||||||
if (opts.exportImages) types.push('image')
|
if (opts.exportImages) types.push('image')
|
||||||
if (opts.exportVideos) types.push('video')
|
if (opts.exportVideos) types.push('video')
|
||||||
if (opts.exportEmojis) types.push('emoji')
|
if (opts.exportEmojis) types.push('emoji')
|
||||||
if (opts.exportFiles) types.push('file')
|
|
||||||
}
|
}
|
||||||
return types
|
return types
|
||||||
}
|
}
|
||||||
@@ -4963,8 +4937,7 @@ function ExportPage() {
|
|||||||
images: options.exportImages,
|
images: options.exportImages,
|
||||||
voices: options.exportVoices,
|
voices: options.exportVoices,
|
||||||
videos: options.exportVideos,
|
videos: options.exportVideos,
|
||||||
emojis: options.exportEmojis,
|
emojis: options.exportEmojis
|
||||||
files: options.exportFiles
|
|
||||||
})
|
})
|
||||||
await configService.setExportDefaultVoiceAsText(options.exportVoiceAsText)
|
await configService.setExportDefaultVoiceAsText(options.exportVoiceAsText)
|
||||||
await configService.setExportDefaultExcelCompactColumns(options.excelCompactColumns)
|
await configService.setExportDefaultExcelCompactColumns(options.excelCompactColumns)
|
||||||
@@ -6982,12 +6955,11 @@ function ExportPage() {
|
|||||||
setExportDefaultMedia(mediaPatch)
|
setExportDefaultMedia(mediaPatch)
|
||||||
setOptions(prev => ({
|
setOptions(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
exportMedia: Boolean(mediaPatch.images || mediaPatch.voices || mediaPatch.videos || mediaPatch.emojis || mediaPatch.files),
|
exportMedia: Boolean(mediaPatch.images || mediaPatch.voices || mediaPatch.videos || mediaPatch.emojis),
|
||||||
exportImages: mediaPatch.images,
|
exportImages: mediaPatch.images,
|
||||||
exportVoices: mediaPatch.voices,
|
exportVoices: mediaPatch.voices,
|
||||||
exportVideos: mediaPatch.videos,
|
exportVideos: mediaPatch.videos,
|
||||||
exportEmojis: mediaPatch.emojis,
|
exportEmojis: mediaPatch.emojis
|
||||||
exportFiles: mediaPatch.files
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
if (typeof patch.voiceAsText === 'boolean') {
|
if (typeof patch.voiceAsText === 'boolean') {
|
||||||
@@ -8187,36 +8159,15 @@ function ExportPage() {
|
|||||||
<label><input type="checkbox" checked={options.exportVoices} onChange={event => setOptions(prev => ({ ...prev, exportVoices: event.target.checked }))} /> 语音</label>
|
<label><input type="checkbox" checked={options.exportVoices} onChange={event => setOptions(prev => ({ ...prev, exportVoices: event.target.checked }))} /> 语音</label>
|
||||||
<label><input type="checkbox" checked={options.exportVideos} onChange={event => setOptions(prev => ({ ...prev, exportVideos: event.target.checked }))} /> 视频</label>
|
<label><input type="checkbox" checked={options.exportVideos} onChange={event => setOptions(prev => ({ ...prev, exportVideos: event.target.checked }))} /> 视频</label>
|
||||||
<label><input type="checkbox" checked={options.exportEmojis} onChange={event => setOptions(prev => ({ ...prev, exportEmojis: event.target.checked }))} /> 表情包</label>
|
<label><input type="checkbox" checked={options.exportEmojis} onChange={event => setOptions(prev => ({ ...prev, exportEmojis: event.target.checked }))} /> 表情包</label>
|
||||||
<label><input type="checkbox" checked={options.exportFiles} onChange={event => setOptions(prev => ({ ...prev, exportFiles: event.target.checked }))} /> 文件</label>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{exportDialog.scope !== 'sns' && options.exportFiles && (
|
{exportDialog.scope === 'sns' && (
|
||||||
<div className="format-note">文件导出会优先使用消息里的 MD5 做校验;若设置了大小上限,则仅导出不超过该值的文件。</div>
|
<div className="format-note">全不勾选时仅导出文本信息,不导出媒体文件。</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{shouldShowMediaSection && exportDialog.scope !== 'sns' && options.exportFiles && (
|
|
||||||
<div className="dialog-section">
|
|
||||||
<h4>文件大小上限</h4>
|
|
||||||
<div className="format-note">仅导出不超过该大小的文件,0 表示不限制。</div>
|
|
||||||
<div className="dialog-input-row">
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
min={0}
|
|
||||||
step={10}
|
|
||||||
value={options.maxFileSizeMb}
|
|
||||||
onChange={event => {
|
|
||||||
const raw = Number(event.target.value)
|
|
||||||
setOptions(prev => ({ ...prev, maxFileSizeMb: Number.isFinite(raw) ? Math.max(0, Math.floor(raw)) : 0 }))
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<span>MB</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{shouldShowImageDeepSearchToggle && (
|
{shouldShowImageDeepSearchToggle && (
|
||||||
<div className="dialog-section">
|
<div className="dialog-section">
|
||||||
<div className="dialog-switch-row">
|
<div className="dialog-switch-row">
|
||||||
|
|||||||
@@ -2508,9 +2508,7 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) {
|
|||||||
<div className="about-footer">
|
<div className="about-footer">
|
||||||
<p className="about-desc">微信聊天记录分析工具</p>
|
<p className="about-desc">微信聊天记录分析工具</p>
|
||||||
<div className="about-links">
|
<div className="about-links">
|
||||||
<a href="#" onClick={(e) => { e.preventDefault(); window.electronAPI.shell.openExternal('https://weflow.top') }}>官网</a>
|
<a href="#" onClick={(e) => { e.preventDefault(); window.electronAPI.shell.openExternal('https://github.com/hicccc77/WeFlow') }}>官网</a>
|
||||||
<span>·</span>
|
|
||||||
<a href="#" onClick={(e) => { e.preventDefault(); window.electronAPI.shell.openExternal('https://github.com/hicccc77/WeFlow') }}>GitHub 仓库</a>
|
|
||||||
<span>·</span>
|
<span>·</span>
|
||||||
<a href="#" onClick={(e) => { e.preventDefault(); window.electronAPI.shell.openExternal('https://chatlab.fun') }}>ChatLab</a>
|
<a href="#" onClick={(e) => { e.preventDefault(); window.electronAPI.shell.openExternal('https://chatlab.fun') }}>ChatLab</a>
|
||||||
<span>·</span>
|
<span>·</span>
|
||||||
|
|||||||
@@ -94,7 +94,6 @@ export interface ExportDefaultMediaConfig {
|
|||||||
videos: boolean
|
videos: boolean
|
||||||
voices: boolean
|
voices: boolean
|
||||||
emojis: boolean
|
emojis: boolean
|
||||||
files: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type WindowCloseBehavior = 'ask' | 'tray' | 'quit'
|
export type WindowCloseBehavior = 'ask' | 'tray' | 'quit'
|
||||||
@@ -105,8 +104,7 @@ const DEFAULT_EXPORT_MEDIA_CONFIG: ExportDefaultMediaConfig = {
|
|||||||
images: true,
|
images: true,
|
||||||
videos: true,
|
videos: true,
|
||||||
voices: true,
|
voices: true,
|
||||||
emojis: true,
|
emojis: true
|
||||||
files: true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取解密密钥
|
// 获取解密密钥
|
||||||
@@ -425,8 +423,7 @@ export async function getExportDefaultMedia(): Promise<ExportDefaultMediaConfig
|
|||||||
images: value,
|
images: value,
|
||||||
videos: value,
|
videos: value,
|
||||||
voices: value,
|
voices: value,
|
||||||
emojis: value,
|
emojis: value
|
||||||
files: value
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (value && typeof value === 'object') {
|
if (value && typeof value === 'object') {
|
||||||
@@ -435,8 +432,7 @@ export async function getExportDefaultMedia(): Promise<ExportDefaultMediaConfig
|
|||||||
images: typeof raw.images === 'boolean' ? raw.images : DEFAULT_EXPORT_MEDIA_CONFIG.images,
|
images: typeof raw.images === 'boolean' ? raw.images : DEFAULT_EXPORT_MEDIA_CONFIG.images,
|
||||||
videos: typeof raw.videos === 'boolean' ? raw.videos : DEFAULT_EXPORT_MEDIA_CONFIG.videos,
|
videos: typeof raw.videos === 'boolean' ? raw.videos : DEFAULT_EXPORT_MEDIA_CONFIG.videos,
|
||||||
voices: typeof raw.voices === 'boolean' ? raw.voices : DEFAULT_EXPORT_MEDIA_CONFIG.voices,
|
voices: typeof raw.voices === 'boolean' ? raw.voices : DEFAULT_EXPORT_MEDIA_CONFIG.voices,
|
||||||
emojis: typeof raw.emojis === 'boolean' ? raw.emojis : DEFAULT_EXPORT_MEDIA_CONFIG.emojis,
|
emojis: typeof raw.emojis === 'boolean' ? raw.emojis : DEFAULT_EXPORT_MEDIA_CONFIG.emojis
|
||||||
files: typeof raw.files === 'boolean' ? raw.files : DEFAULT_EXPORT_MEDIA_CONFIG.files
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
@@ -448,8 +444,7 @@ export async function setExportDefaultMedia(media: ExportDefaultMediaConfig): Pr
|
|||||||
images: media.images,
|
images: media.images,
|
||||||
videos: media.videos,
|
videos: media.videos,
|
||||||
voices: media.voices,
|
voices: media.voices,
|
||||||
emojis: media.emojis,
|
emojis: media.emojis
|
||||||
files: media.files
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4
src/types/electron.d.ts
vendored
4
src/types/electron.d.ts
vendored
@@ -881,7 +881,7 @@ export interface ElectronAPI {
|
|||||||
|
|
||||||
export interface ExportOptions {
|
export interface ExportOptions {
|
||||||
format: 'chatlab' | 'chatlab-jsonl' | 'json' | 'arkme-json' | 'html' | 'txt' | 'excel' | 'weclone' | 'sql'
|
format: 'chatlab' | 'chatlab-jsonl' | 'json' | 'arkme-json' | 'html' | 'txt' | 'excel' | 'weclone' | 'sql'
|
||||||
contentType?: 'text' | 'voice' | 'image' | 'video' | 'emoji' | 'file'
|
contentType?: 'text' | 'voice' | 'image' | 'video' | 'emoji'
|
||||||
dateRange?: { start: number; end: number } | null
|
dateRange?: { start: number; end: number } | null
|
||||||
senderUsername?: string
|
senderUsername?: string
|
||||||
fileNameSuffix?: string
|
fileNameSuffix?: string
|
||||||
@@ -891,8 +891,6 @@ export interface ExportOptions {
|
|||||||
exportVoices?: boolean
|
exportVoices?: boolean
|
||||||
exportVideos?: boolean
|
exportVideos?: boolean
|
||||||
exportEmojis?: boolean
|
exportEmojis?: boolean
|
||||||
exportFiles?: boolean
|
|
||||||
maxFileSizeMb?: number
|
|
||||||
exportVoiceAsText?: boolean
|
exportVoiceAsText?: boolean
|
||||||
excelCompactColumns?: boolean
|
excelCompactColumns?: boolean
|
||||||
txtColumns?: string[]
|
txtColumns?: string[]
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ export interface Message {
|
|||||||
fileName?: string // 文件名
|
fileName?: string // 文件名
|
||||||
fileSize?: number // 文件大小
|
fileSize?: number // 文件大小
|
||||||
fileExt?: string // 文件扩展名
|
fileExt?: string // 文件扩展名
|
||||||
fileMd5?: string // 文件 MD5
|
|
||||||
xmlType?: string // XML 中的 type 字段
|
xmlType?: string // XML 中的 type 字段
|
||||||
appMsgKind?: string // 归一化 appmsg 类型
|
appMsgKind?: string // 归一化 appmsg 类型
|
||||||
appMsgDesc?: string
|
appMsgDesc?: string
|
||||||
|
|||||||
Reference in New Issue
Block a user