Add bulk history actions and selection UX #37 (#42)

* Add collapsed playlist progress

* Improve history bulk actions and selection UX

* Fix ffmpeg download resolution in setup script
This commit is contained in:
Nexmoe
2025-12-20 12:07:13 +08:00
committed by GitHub
parent 58a4d2da36
commit dbcd77963f
15 changed files with 862 additions and 102 deletions

View File

@@ -25,6 +25,21 @@ class HistoryService extends IpcService {
return historyManager.removeHistoryItem(id)
}
@IpcMethod()
removeHistoryItems(_context: IpcContext, ids: string[]): number {
return historyManager.removeHistoryItems(ids)
}
@IpcMethod()
removeHistoryByPlaylistId(_context: IpcContext, playlistId: string): number {
return historyManager.removeHistoryByPlaylistId(playlistId)
}
@IpcMethod()
clearHistory(_context: IpcContext): void {
historyManager.clearHistory()
}
@IpcMethod()
getHistoryCount(_context: IpcContext): {
active: number

View File

@@ -1,7 +1,7 @@
import { existsSync, readFileSync, renameSync } from 'node:fs'
import { join } from 'node:path'
import DatabaseConstructor from 'better-sqlite3'
import { eq, sql } from 'drizzle-orm'
import { eq, inArray, sql } from 'drizzle-orm'
import type { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3'
import { drizzle } from 'drizzle-orm/better-sqlite3'
import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'
@@ -494,6 +494,61 @@ class HistoryManager {
}
}
removeHistoryItems(ids: string[]): number {
const uniqueIds = Array.from(new Set(ids)).filter((id) => id.trim().length > 0)
if (uniqueIds.length === 0) {
return 0
}
let removedCount = 0
try {
const database = this.getDatabase()
const result = database
.delete(downloadHistoryTable)
.where(inArray(downloadHistoryTable.id, uniqueIds))
.run()
for (const id of uniqueIds) {
if (this.history.delete(id)) {
removedCount++
}
}
if ((result.changes ?? 0) > removedCount) {
removedCount = result.changes ?? removedCount
}
return removedCount
} catch (error) {
logger.error('history-db failed to delete items', { count: uniqueIds.length, error })
return removedCount
}
}
removeHistoryByPlaylistId(playlistId: string): number {
const normalized = playlistId.trim()
if (!normalized) {
return 0
}
let removedCount = 0
try {
const database = this.getDatabase()
const result = database
.delete(downloadHistoryTable)
.where(eq(downloadHistoryTable.playlistId, normalized))
.run()
for (const [id, item] of this.history.entries()) {
if (item.playlistId === normalized) {
this.history.delete(id)
removedCount++
}
}
if ((result.changes ?? 0) > removedCount) {
removedCount = result.changes ?? removedCount
}
return removedCount
} catch (error) {
logger.error('history-db failed to delete playlist items', { playlistId: normalized, error })
return removedCount
}
}
clearHistory(): void {
try {
const database = this.getDatabase()