App Mode - Progress/outputs - 5 (#9028)

## Summary

Adds new store for tracking outputs lin linear mode and reworks outputs
to display the following: skeleton -> latent preview -> node output ->
job result.

## Changes

- **What**: 
- New store for wrangling various events into a usable list of live
outputs
- Replace manual list with reka-ui list box
- Extract various composables

## Review Focus
Getting all the events and stores aligned to happen consistently and in
the correct order was a challenge, unifying the various sources. so
suggestions there would be good

## Screenshots (if applicable)


https://github.com/user-attachments/assets/13449780-ee48-4d9a-b3aa-51dca0a124c7

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9028-App-Mode-Progress-outputs-5-30d6d73d3650817aaa9dee622fffe426)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
pythongosssss
2026-02-23 18:43:25 +00:00
committed by GitHub
parent b29dbec916
commit f811b173c6
20 changed files with 1484 additions and 392 deletions

View File

@@ -0,0 +1,65 @@
import { useAsyncState } from '@vueuse/core'
import type { MaybeRef } from 'vue'
import { useMediaAssets } from '@/platform/assets/composables/media/useMediaAssets'
import type { IAssetsProvider } from '@/platform/assets/composables/media/IAssetsProvider'
import { getOutputAssetMetadata } from '@/platform/assets/schemas/assetMetadataSchema'
import type { AssetItem } from '@/platform/assets/schemas/assetSchema'
import { flattenNodeOutput } from '@/renderer/extensions/linearMode/flattenNodeOutput'
import { useLinearOutputStore } from '@/renderer/extensions/linearMode/linearOutputStore'
import { getJobDetail } from '@/services/jobOutputCache'
import type { ResultItemImpl } from '@/stores/queueStore'
export function useOutputHistory(): {
outputs: IAssetsProvider
allOutputs: (item?: AssetItem) => MaybeRef<ResultItemImpl[]>
} {
const outputs = useMediaAssets('output')
void outputs.fetchMediaList()
const linearStore = useLinearOutputStore()
const outputsCache: Record<string, MaybeRef<ResultItemImpl[]>> = {}
function allOutputs(item?: AssetItem): MaybeRef<ResultItemImpl[]> {
if (item?.id && outputsCache[item.id]) return outputsCache[item.id]
const user_metadata = getOutputAssetMetadata(item?.user_metadata)
if (!user_metadata) return []
// For recently completed jobs still pending resolve, derive order from
// the in-progress items which are in correct execution order.
if (linearStore.pendingResolve.has(user_metadata.jobId)) {
const ordered = linearStore.inProgressItems
.filter((i) => i.jobId === user_metadata.jobId && i.output)
.map((i) => i.output!)
if (ordered.length > 0) {
outputsCache[item!.id] = ordered
return ordered
}
}
if (
user_metadata.allOutputs &&
user_metadata.outputCount &&
user_metadata.outputCount <= user_metadata.allOutputs.length
) {
const reversed = user_metadata.allOutputs.toReversed()
outputsCache[item!.id] = reversed
return reversed
}
const outputRef = useAsyncState(
getJobDetail(user_metadata.jobId).then((jobDetail) => {
if (!jobDetail?.outputs) return []
return Object.entries(jobDetail.outputs)
.flatMap(flattenNodeOutput)
.toReversed()
}),
[]
).state
outputsCache[item!.id] = outputRef
return outputRef
}
return { outputs, allOutputs }
}