@owdproject/core
Version:
Nuxt Desktop module for browser desktop experiences (windows, shell, apps)
93 lines (79 loc) • 2.76 kB
text/typescript
import { useDebounceFn } from '@vueuse/core'
import { nextTick, ref, shallowRef, watch } from 'vue'
import { useDesktopWorkspaceStore } from '@owdproject/core/runtime/stores/storeDesktopWorkspace'
import { captureElementToCanvas } from '../utils/utilCaptureElementToCanvas'
export type WorkspaceRootResolver = (
workspaceId: string,
) => HTMLElement | null | undefined
export type UseWorkspaceOverviewCaptureOptions = {
/** Delay before capturing after overview opens (ms). Default 150. */
debounceMs?: number
/** JPEG quality for thumbnail data URLs (0–1). Default 0.7. */
jpegQuality?: number
/** Passed through to html2canvas. */
captureOptions?: Record<string, unknown>
}
/**
* Captures workspace desktop roots as JPEG data URLs while workspace overview is open.
* Themes supply a resolver that maps each workspace id to its DOM root (e.g. a layer wrapping
* {@link DesktopApplicationRender} with `workspace-filter`).
*/
export function useWorkspaceOverviewCapture(
resolveWorkspaceRoot: WorkspaceRootResolver,
options: UseWorkspaceOverviewCaptureOptions = {},
) {
const desktopWorkspaceStore = useDesktopWorkspaceStore()
const thumbnails = shallowRef(new Map<string, string>())
const isCapturing = ref(false)
const debounceMs = options.debounceMs ?? 150
const jpegQuality = options.jpegQuality ?? 0.7
async function captureWorkspace(workspaceId: string): Promise<string | null> {
const element = resolveWorkspaceRoot(workspaceId)
const canvas = await captureElementToCanvas(element, options.captureOptions)
if (!canvas) return null
return canvas.toDataURL('image/jpeg', jpegQuality)
}
async function refreshThumbnails() {
if (!desktopWorkspaceStore.overview) return
isCapturing.value = true
const next = new Map<string, string>()
try {
await nextTick()
const ids = [...desktopWorkspaceStore.list]
await Promise.all(
ids.map(async (id) => {
const dataUrl = await captureWorkspace(id)
if (dataUrl) next.set(id, dataUrl)
}),
)
thumbnails.value = next
} finally {
isCapturing.value = false
}
}
const scheduleRefresh = useDebounceFn(() => {
void refreshThumbnails()
}, debounceMs)
watch(
() => desktopWorkspaceStore.overview,
(open) => {
if (open) scheduleRefresh()
else thumbnails.value = new Map()
},
)
watch(
() => desktopWorkspaceStore.list.join('\0'),
() => {
if (desktopWorkspaceStore.overview) scheduleRefresh()
},
)
function thumbnailFor(workspaceId: string): string | undefined {
return thumbnails.value.get(workspaceId)
}
return {
thumbnails,
isCapturing,
refreshThumbnails,
thumbnailFor,
}
}