mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-26 00:31:20 -08:00
refactor(auto-thumbnail): [PKG-AUTO-THUMB-03] type internal extraction contracts
This commit is contained in:
1 parent
00e81309ca
commit
6c989deccd
20 files changed
+3968
-48
No files matched your search
@@ -0,0 +1,132 @@
|
||||
import type { Cleanup, ExtractionJob, ThumbnailSheet } from './types'
|
||||
|
||||
export function cleanupAll(actions: Cleanup[]) {
|
||||
let failure: unknown
|
||||
let failed = false
|
||||
for (const action of actions) {
|
||||
try {
|
||||
action()
|
||||
}
|
||||
catch (error) {
|
||||
if (!failed) {
|
||||
failed = true
|
||||
failure = error
|
||||
}
|
||||
}
|
||||
}
|
||||
return { failed, failure }
|
||||
}
|
||||
|
||||
export default function createSession(publish: (sheet: ThumbnailSheet) => void, report: (error: unknown) => void) {
|
||||
let closed = false
|
||||
let current: ExtractionJob | undefined
|
||||
let lastUrl: string | undefined
|
||||
const urls = new Set<string>()
|
||||
|
||||
function release(url: string | undefined) {
|
||||
if (url !== undefined && urls.delete(url))
|
||||
URL.revokeObjectURL(url)
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
const previous = current
|
||||
current = undefined
|
||||
previous?.dispose()
|
||||
}
|
||||
|
||||
function destroy() {
|
||||
if (closed)
|
||||
return
|
||||
closed = true
|
||||
const result = cleanupAll([cancel, ...[...urls].map(url => () => release(url))])
|
||||
lastUrl = undefined
|
||||
if (result.failed)
|
||||
report(result.failure)
|
||||
}
|
||||
|
||||
function start() {
|
||||
if (closed)
|
||||
return
|
||||
// Install the replacement before cleanup, which can reenter through host APIs.
|
||||
const previous = current
|
||||
const actions: Cleanup[] = []
|
||||
let disposed = false
|
||||
const job: ExtractionJob = {
|
||||
active: () => !closed && !disposed && current === job,
|
||||
own(action) {
|
||||
if (disposed) {
|
||||
const result = cleanupAll([action])
|
||||
if (result.failed)
|
||||
report(result.failure)
|
||||
}
|
||||
else {
|
||||
actions.push(action)
|
||||
}
|
||||
},
|
||||
dispose() {
|
||||
if (disposed)
|
||||
return
|
||||
disposed = true
|
||||
if (current === job)
|
||||
current = undefined
|
||||
const result = cleanupAll(actions.splice(0).reverse())
|
||||
if (result.failed)
|
||||
report(result.failure)
|
||||
},
|
||||
fail(error) {
|
||||
if (!job.active())
|
||||
return
|
||||
job.dispose()
|
||||
report(error)
|
||||
},
|
||||
guard(callback) {
|
||||
return (...args) => {
|
||||
if (!job.active())
|
||||
return
|
||||
try {
|
||||
return callback(...args)
|
||||
}
|
||||
catch (error) {
|
||||
job.fail(error)
|
||||
}
|
||||
}
|
||||
},
|
||||
publish(blob, config) {
|
||||
if (!job.active())
|
||||
return
|
||||
if (!blob)
|
||||
throw new Error('Auto-thumbnail encoding returned no Blob')
|
||||
const url = URL.createObjectURL(blob)
|
||||
urls.add(url)
|
||||
if (!job.active()) {
|
||||
release(url)
|
||||
return
|
||||
}
|
||||
const previousUrl = lastUrl
|
||||
lastUrl = url
|
||||
try {
|
||||
publish({ url, ...config })
|
||||
}
|
||||
catch (error) {
|
||||
if (lastUrl === url)
|
||||
lastUrl = previousUrl !== undefined && urls.has(previousUrl) ? previousUrl : undefined
|
||||
const result = cleanupAll([() => release(url)])
|
||||
if (result.failed)
|
||||
report(result.failure)
|
||||
throw error
|
||||
}
|
||||
release(previousUrl)
|
||||
},
|
||||
}
|
||||
current = job
|
||||
previous?.dispose()
|
||||
return job
|
||||
}
|
||||
|
||||
return {
|
||||
start,
|
||||
cancel,
|
||||
destroy,
|
||||
get closed() { return closed },
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user