mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-24 23:06:51 +00:00
feat(sns-export): split media export selection into image/live/video
This commit is contained in:
@@ -1085,13 +1085,30 @@ class SnsService {
|
|||||||
usernames?: string[]
|
usernames?: string[]
|
||||||
keyword?: string
|
keyword?: string
|
||||||
exportMedia?: boolean
|
exportMedia?: boolean
|
||||||
|
exportImages?: boolean
|
||||||
|
exportLivePhotos?: boolean
|
||||||
|
exportVideos?: boolean
|
||||||
startTime?: number
|
startTime?: number
|
||||||
endTime?: number
|
endTime?: number
|
||||||
}, progressCallback?: (progress: { current: number; total: number; status: string }) => void, control?: {
|
}, progressCallback?: (progress: { current: number; total: number; status: string }) => void, control?: {
|
||||||
shouldPause?: () => boolean
|
shouldPause?: () => boolean
|
||||||
shouldStop?: () => boolean
|
shouldStop?: () => boolean
|
||||||
}): Promise<{ success: boolean; filePath?: string; postCount?: number; mediaCount?: number; paused?: boolean; stopped?: boolean; error?: string }> {
|
}): Promise<{ success: boolean; filePath?: string; postCount?: number; mediaCount?: number; paused?: boolean; stopped?: boolean; error?: string }> {
|
||||||
const { outputDir, format, usernames, keyword, exportMedia = false, startTime, endTime } = options
|
const { outputDir, format, usernames, keyword, startTime, endTime } = options
|
||||||
|
const hasExplicitMediaSelection =
|
||||||
|
typeof options.exportImages === 'boolean' ||
|
||||||
|
typeof options.exportLivePhotos === 'boolean' ||
|
||||||
|
typeof options.exportVideos === 'boolean'
|
||||||
|
const shouldExportImages = hasExplicitMediaSelection
|
||||||
|
? options.exportImages === true
|
||||||
|
: options.exportMedia === true
|
||||||
|
const shouldExportLivePhotos = hasExplicitMediaSelection
|
||||||
|
? options.exportLivePhotos === true
|
||||||
|
: options.exportMedia === true
|
||||||
|
const shouldExportVideos = hasExplicitMediaSelection
|
||||||
|
? options.exportVideos === true
|
||||||
|
: options.exportMedia === true
|
||||||
|
const shouldExportMedia = shouldExportImages || shouldExportLivePhotos || shouldExportVideos
|
||||||
const getControlState = (): 'paused' | 'stopped' | null => {
|
const getControlState = (): 'paused' | 'stopped' | null => {
|
||||||
if (control?.shouldStop?.()) return 'stopped'
|
if (control?.shouldStop?.()) return 'stopped'
|
||||||
if (control?.shouldPause?.()) return 'paused'
|
if (control?.shouldPause?.()) return 'paused'
|
||||||
@@ -1149,15 +1166,54 @@ class SnsService {
|
|||||||
let mediaCount = 0
|
let mediaCount = 0
|
||||||
const mediaDir = join(outputDir, 'media')
|
const mediaDir = join(outputDir, 'media')
|
||||||
|
|
||||||
if (exportMedia) {
|
if (shouldExportMedia) {
|
||||||
if (!existsSync(mediaDir)) {
|
if (!existsSync(mediaDir)) {
|
||||||
mkdirSync(mediaDir, { recursive: true })
|
mkdirSync(mediaDir, { recursive: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 收集所有媒体下载任务
|
// 收集所有媒体下载任务
|
||||||
const mediaTasks: { media: SnsMedia; postId: string; mi: number }[] = []
|
const mediaTasks: Array<{
|
||||||
|
kind: 'image' | 'video' | 'livephoto'
|
||||||
|
media: SnsMedia
|
||||||
|
url: string
|
||||||
|
key?: string
|
||||||
|
postId: string
|
||||||
|
mi: number
|
||||||
|
}> = []
|
||||||
for (const post of allPosts) {
|
for (const post of allPosts) {
|
||||||
post.media.forEach((media, mi) => mediaTasks.push({ media, postId: post.id, mi }))
|
post.media.forEach((media, mi) => {
|
||||||
|
const isVideo = isVideoUrl(media.url)
|
||||||
|
if (shouldExportImages && !isVideo && media.url) {
|
||||||
|
mediaTasks.push({
|
||||||
|
kind: 'image',
|
||||||
|
media,
|
||||||
|
url: media.url,
|
||||||
|
key: media.key,
|
||||||
|
postId: post.id,
|
||||||
|
mi
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (shouldExportVideos && isVideo && media.url) {
|
||||||
|
mediaTasks.push({
|
||||||
|
kind: 'video',
|
||||||
|
media,
|
||||||
|
url: media.url,
|
||||||
|
key: media.key,
|
||||||
|
postId: post.id,
|
||||||
|
mi
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (shouldExportLivePhotos && media.livePhoto?.url) {
|
||||||
|
mediaTasks.push({
|
||||||
|
kind: 'livephoto',
|
||||||
|
media,
|
||||||
|
url: media.livePhoto.url,
|
||||||
|
key: media.livePhoto.key || media.key,
|
||||||
|
postId: post.id,
|
||||||
|
mi
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 并发下载(5路)
|
// 并发下载(5路)
|
||||||
@@ -1166,29 +1222,42 @@ class SnsService {
|
|||||||
const runTask = async (task: typeof mediaTasks[0]) => {
|
const runTask = async (task: typeof mediaTasks[0]) => {
|
||||||
const { media, postId, mi } = task
|
const { media, postId, mi } = task
|
||||||
try {
|
try {
|
||||||
const isVideo = isVideoUrl(media.url)
|
const isVideo = task.kind === 'video' || task.kind === 'livephoto' || isVideoUrl(task.url)
|
||||||
const ext = isVideo ? 'mp4' : 'jpg'
|
const ext = isVideo ? 'mp4' : 'jpg'
|
||||||
const fileName = `${postId}_${mi}.${ext}`
|
const suffix = task.kind === 'livephoto' ? '_live' : ''
|
||||||
|
const fileName = `${postId}_${mi}${suffix}.${ext}`
|
||||||
const filePath = join(mediaDir, fileName)
|
const filePath = join(mediaDir, fileName)
|
||||||
|
|
||||||
if (existsSync(filePath)) {
|
if (existsSync(filePath)) {
|
||||||
;(media as any).localPath = `media/${fileName}`
|
if (task.kind === 'livephoto') {
|
||||||
|
if (media.livePhoto) (media.livePhoto as any).localPath = `media/${fileName}`
|
||||||
|
} else {
|
||||||
|
;(media as any).localPath = `media/${fileName}`
|
||||||
|
}
|
||||||
mediaCount++
|
mediaCount++
|
||||||
} else {
|
} else {
|
||||||
const result = await this.fetchAndDecryptImage(media.url, media.key)
|
const result = await this.fetchAndDecryptImage(task.url, task.key)
|
||||||
if (result.success && result.data) {
|
if (result.success && result.data) {
|
||||||
await writeFile(filePath, result.data)
|
await writeFile(filePath, result.data)
|
||||||
;(media as any).localPath = `media/${fileName}`
|
if (task.kind === 'livephoto') {
|
||||||
|
if (media.livePhoto) (media.livePhoto as any).localPath = `media/${fileName}`
|
||||||
|
} else {
|
||||||
|
;(media as any).localPath = `media/${fileName}`
|
||||||
|
}
|
||||||
mediaCount++
|
mediaCount++
|
||||||
} else if (result.success && result.cachePath) {
|
} else if (result.success && result.cachePath) {
|
||||||
const cachedData = await readFile(result.cachePath)
|
const cachedData = await readFile(result.cachePath)
|
||||||
await writeFile(filePath, cachedData)
|
await writeFile(filePath, cachedData)
|
||||||
;(media as any).localPath = `media/${fileName}`
|
if (task.kind === 'livephoto') {
|
||||||
|
if (media.livePhoto) (media.livePhoto as any).localPath = `media/${fileName}`
|
||||||
|
} else {
|
||||||
|
;(media as any).localPath = `media/${fileName}`
|
||||||
|
}
|
||||||
mediaCount++
|
mediaCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn(`[SnsExport] 媒体下载失败: ${task.media.url}`, e)
|
console.warn(`[SnsExport] 媒体下载失败: ${task.url}`, e)
|
||||||
}
|
}
|
||||||
done++
|
done++
|
||||||
progressCallback?.({ current: done, total: mediaTasks.length, status: `正在下载媒体 (${done}/${mediaTasks.length})...` })
|
progressCallback?.({ current: done, total: mediaTasks.length, status: `正在下载媒体 (${done}/${mediaTasks.length})...` })
|
||||||
@@ -1323,7 +1392,12 @@ class SnsService {
|
|||||||
media: post.media.map(m => ({
|
media: post.media.map(m => ({
|
||||||
url: m.url,
|
url: m.url,
|
||||||
thumb: m.thumb,
|
thumb: m.thumb,
|
||||||
localPath: (m as any).localPath || undefined
|
localPath: (m as any).localPath || undefined,
|
||||||
|
livePhoto: m.livePhoto ? {
|
||||||
|
url: m.livePhoto.url,
|
||||||
|
thumb: m.livePhoto.thumb,
|
||||||
|
localPath: (m.livePhoto as any).localPath || undefined
|
||||||
|
} : undefined
|
||||||
})),
|
})),
|
||||||
likes: post.likes,
|
likes: post.likes,
|
||||||
comments: post.comments,
|
comments: post.comments,
|
||||||
@@ -1343,6 +1417,11 @@ class SnsService {
|
|||||||
exportTime: new Date().toISOString(),
|
exportTime: new Date().toISOString(),
|
||||||
format: 'arkmejson',
|
format: 'arkmejson',
|
||||||
schemaVersion: '1.0.0',
|
schemaVersion: '1.0.0',
|
||||||
|
mediaSelection: {
|
||||||
|
images: shouldExportImages,
|
||||||
|
livePhotos: shouldExportLivePhotos,
|
||||||
|
videos: shouldExportVideos
|
||||||
|
},
|
||||||
totalPosts: allPosts.length,
|
totalPosts: allPosts.length,
|
||||||
filters: {
|
filters: {
|
||||||
usernames: usernames || [],
|
usernames: usernames || [],
|
||||||
|
|||||||
@@ -112,7 +112,9 @@ interface ExportTaskPayload {
|
|||||||
sessionNames: string[]
|
sessionNames: string[]
|
||||||
snsOptions?: {
|
snsOptions?: {
|
||||||
format: SnsTimelineExportFormat
|
format: SnsTimelineExportFormat
|
||||||
exportMedia?: boolean
|
exportImages?: boolean
|
||||||
|
exportLivePhotos?: boolean
|
||||||
|
exportVideos?: boolean
|
||||||
startTime?: number
|
startTime?: number
|
||||||
endTime?: number
|
endTime?: number
|
||||||
}
|
}
|
||||||
@@ -878,6 +880,9 @@ function ExportPage() {
|
|||||||
const [exportFolder, setExportFolder] = useState('')
|
const [exportFolder, setExportFolder] = useState('')
|
||||||
const [writeLayout, setWriteLayout] = useState<configService.ExportWriteLayout>('A')
|
const [writeLayout, setWriteLayout] = useState<configService.ExportWriteLayout>('A')
|
||||||
const [snsExportFormat, setSnsExportFormat] = useState<SnsTimelineExportFormat>('html')
|
const [snsExportFormat, setSnsExportFormat] = useState<SnsTimelineExportFormat>('html')
|
||||||
|
const [snsExportImages, setSnsExportImages] = useState(false)
|
||||||
|
const [snsExportLivePhotos, setSnsExportLivePhotos] = useState(false)
|
||||||
|
const [snsExportVideos, setSnsExportVideos] = useState(false)
|
||||||
|
|
||||||
const [options, setOptions] = useState<ExportOptions>({
|
const [options, setOptions] = useState<ExportOptions>({
|
||||||
format: 'arkme-json',
|
format: 'arkme-json',
|
||||||
@@ -2038,7 +2043,6 @@ function ExportPage() {
|
|||||||
|
|
||||||
const buildSnsExportOptions = () => {
|
const buildSnsExportOptions = () => {
|
||||||
const format: SnsTimelineExportFormat = snsExportFormat
|
const format: SnsTimelineExportFormat = snsExportFormat
|
||||||
const exportMediaEnabled = Boolean(options.exportImages || options.exportVoices || options.exportVideos || options.exportEmojis)
|
|
||||||
const dateRange = options.useAllTime
|
const dateRange = options.useAllTime
|
||||||
? null
|
? null
|
||||||
: options.dateRange
|
: options.dateRange
|
||||||
@@ -2050,7 +2054,9 @@ function ExportPage() {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
format,
|
format,
|
||||||
exportMedia: exportMediaEnabled,
|
exportImages: snsExportImages,
|
||||||
|
exportLivePhotos: snsExportLivePhotos,
|
||||||
|
exportVideos: snsExportVideos,
|
||||||
startTime: dateRange?.startTime,
|
startTime: dateRange?.startTime,
|
||||||
endTime: dateRange?.endTime
|
endTime: dateRange?.endTime
|
||||||
}
|
}
|
||||||
@@ -2159,11 +2165,13 @@ function ExportPage() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (next.payload.scope === 'sns') {
|
if (next.payload.scope === 'sns') {
|
||||||
const snsOptions = next.payload.snsOptions || { format: 'html' as SnsTimelineExportFormat, exportMedia: false }
|
const snsOptions = next.payload.snsOptions || { format: 'html' as SnsTimelineExportFormat, exportImages: false, exportLivePhotos: false, exportVideos: false }
|
||||||
const result = await window.electronAPI.sns.exportTimeline({
|
const result = await window.electronAPI.sns.exportTimeline({
|
||||||
outputDir: next.payload.outputDir,
|
outputDir: next.payload.outputDir,
|
||||||
format: snsOptions.format,
|
format: snsOptions.format,
|
||||||
exportMedia: snsOptions.exportMedia,
|
exportImages: snsOptions.exportImages,
|
||||||
|
exportLivePhotos: snsOptions.exportLivePhotos,
|
||||||
|
exportVideos: snsOptions.exportVideos,
|
||||||
startTime: snsOptions.startTime,
|
startTime: snsOptions.startTime,
|
||||||
endTime: snsOptions.endTime,
|
endTime: snsOptions.endTime,
|
||||||
taskId: next.id
|
taskId: next.id
|
||||||
@@ -4414,15 +4422,28 @@ function ExportPage() {
|
|||||||
|
|
||||||
{shouldShowMediaSection && (
|
{shouldShowMediaSection && (
|
||||||
<div className="dialog-section">
|
<div className="dialog-section">
|
||||||
<h4>媒体与头像</h4>
|
<h4>{exportDialog.scope === 'sns' ? '媒体文件(可多选)' : '媒体与头像'}</h4>
|
||||||
<div className="media-check-grid">
|
<div className="media-check-grid">
|
||||||
<label><input type="checkbox" checked={options.exportImages} onChange={event => setOptions(prev => ({ ...prev, exportImages: event.target.checked }))} /> 图片</label>
|
{exportDialog.scope === 'sns' ? (
|
||||||
<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={snsExportImages} onChange={event => setSnsExportImages(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={snsExportLivePhotos} onChange={event => setSnsExportLivePhotos(event.target.checked)} /> 实况图</label>
|
||||||
<label><input type="checkbox" checked={options.exportVoiceAsText} onChange={event => setOptions(prev => ({ ...prev, exportVoiceAsText: event.target.checked }))} /> 语音转文字</label>
|
<label><input type="checkbox" checked={snsExportVideos} onChange={event => setSnsExportVideos(event.target.checked)} /> 视频</label>
|
||||||
<label><input type="checkbox" checked={options.exportAvatars} onChange={event => setOptions(prev => ({ ...prev, exportAvatars: event.target.checked }))} /> 导出头像</label>
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<label><input type="checkbox" checked={options.exportImages} onChange={event => setOptions(prev => ({ ...prev, exportImages: 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.exportEmojis} onChange={event => setOptions(prev => ({ ...prev, exportEmojis: event.target.checked }))} /> 表情包</label>
|
||||||
|
<label><input type="checkbox" checked={options.exportVoiceAsText} onChange={event => setOptions(prev => ({ ...prev, exportVoiceAsText: event.target.checked }))} /> 语音转文字</label>
|
||||||
|
<label><input type="checkbox" checked={options.exportAvatars} onChange={event => setOptions(prev => ({ ...prev, exportAvatars: event.target.checked }))} /> 导出头像</label>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{exportDialog.scope === 'sns' && (
|
||||||
|
<div className="format-note">全不勾选时仅导出文本信息,不导出媒体文件。</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -1984,10 +1984,31 @@
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: var(--text-tertiary);
|
color: var(--text-tertiary);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding-left: 24px;
|
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.export-media-check-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--text-primary);
|
||||||
|
padding: 8px 10px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: 8px;
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type='checkbox'] {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.export-progress {
|
.export-progress {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -62,7 +62,9 @@ export default function SnsPage() {
|
|||||||
const [showExportDialog, setShowExportDialog] = useState(false)
|
const [showExportDialog, setShowExportDialog] = useState(false)
|
||||||
const [exportFormat, setExportFormat] = useState<'json' | 'html' | 'arkmejson'>('html')
|
const [exportFormat, setExportFormat] = useState<'json' | 'html' | 'arkmejson'>('html')
|
||||||
const [exportFolder, setExportFolder] = useState('')
|
const [exportFolder, setExportFolder] = useState('')
|
||||||
const [exportMedia, setExportMedia] = useState(false)
|
const [exportImages, setExportImages] = useState(false)
|
||||||
|
const [exportLivePhotos, setExportLivePhotos] = useState(false)
|
||||||
|
const [exportVideos, setExportVideos] = useState(false)
|
||||||
const [exportDateRange, setExportDateRange] = useState<{ start: string; end: string }>({ start: '', end: '' })
|
const [exportDateRange, setExportDateRange] = useState<{ start: string; end: string }>({ start: '', end: '' })
|
||||||
const [isExporting, setIsExporting] = useState(false)
|
const [isExporting, setIsExporting] = useState(false)
|
||||||
const [exportProgress, setExportProgress] = useState<{ current: number; total: number; status: string } | null>(null)
|
const [exportProgress, setExportProgress] = useState<{ current: number; total: number; status: string } | null>(null)
|
||||||
@@ -950,22 +952,40 @@ export default function SnsPage() {
|
|||||||
|
|
||||||
{/* 媒体导出 */}
|
{/* 媒体导出 */}
|
||||||
<div className="export-section">
|
<div className="export-section">
|
||||||
<div className="export-toggle-row">
|
<label className="export-label">
|
||||||
<div className="toggle-label">
|
<Image size={14} />
|
||||||
<Image size={16} />
|
媒体文件(可多选)
|
||||||
<span>导出媒体文件(图片/视频)</span>
|
</label>
|
||||||
</div>
|
<div className="export-media-check-grid">
|
||||||
<button
|
<label>
|
||||||
className={`toggle-switch${exportMedia ? ' active' : ''}`}
|
<input
|
||||||
onClick={() => !isExporting && setExportMedia(!exportMedia)}
|
type="checkbox"
|
||||||
disabled={isExporting}
|
checked={exportImages}
|
||||||
>
|
onChange={(e) => setExportImages(e.target.checked)}
|
||||||
<span className="toggle-knob" />
|
disabled={isExporting}
|
||||||
</button>
|
/>
|
||||||
|
图片
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={exportLivePhotos}
|
||||||
|
onChange={(e) => setExportLivePhotos(e.target.checked)}
|
||||||
|
disabled={isExporting}
|
||||||
|
/>
|
||||||
|
实况图
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={exportVideos}
|
||||||
|
onChange={(e) => setExportVideos(e.target.checked)}
|
||||||
|
disabled={isExporting}
|
||||||
|
/>
|
||||||
|
视频
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
{exportMedia && (
|
<p className="export-media-hint">全不勾选时仅导出文本信息,不导出媒体文件</p>
|
||||||
<p className="export-media-hint">媒体文件将保存到输出目录的 media 子目录中,可能需要较长时间</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 同步提示 */}
|
{/* 同步提示 */}
|
||||||
@@ -1015,7 +1035,9 @@ export default function SnsPage() {
|
|||||||
format: exportFormat,
|
format: exportFormat,
|
||||||
usernames: selectedUsernames.length > 0 ? selectedUsernames : undefined,
|
usernames: selectedUsernames.length > 0 ? selectedUsernames : undefined,
|
||||||
keyword: searchKeyword || undefined,
|
keyword: searchKeyword || undefined,
|
||||||
exportMedia,
|
exportImages,
|
||||||
|
exportLivePhotos,
|
||||||
|
exportVideos,
|
||||||
startTime: exportDateRange.start ? Math.floor(new Date(exportDateRange.start).getTime() / 1000) : undefined,
|
startTime: exportDateRange.start ? Math.floor(new Date(exportDateRange.start).getTime() / 1000) : undefined,
|
||||||
endTime: exportDateRange.end ? Math.floor(new Date(exportDateRange.end + 'T23:59:59').getTime() / 1000) : undefined
|
endTime: exportDateRange.end ? Math.floor(new Date(exportDateRange.end + 'T23:59:59').getTime() / 1000) : undefined
|
||||||
})
|
})
|
||||||
|
|||||||
4
src/types/electron.d.ts
vendored
4
src/types/electron.d.ts
vendored
@@ -719,7 +719,9 @@ export interface ElectronAPI {
|
|||||||
format: 'json' | 'html' | 'arkmejson'
|
format: 'json' | 'html' | 'arkmejson'
|
||||||
usernames?: string[]
|
usernames?: string[]
|
||||||
keyword?: string
|
keyword?: string
|
||||||
exportMedia?: boolean
|
exportImages?: boolean
|
||||||
|
exportLivePhotos?: boolean
|
||||||
|
exportVideos?: boolean
|
||||||
startTime?: number
|
startTime?: number
|
||||||
endTime?: number
|
endTime?: number
|
||||||
taskId?: string
|
taskId?: string
|
||||||
|
|||||||
Reference in New Issue
Block a user