Files
documents/src/composables/useFileViewer.ts
T
Sebastian a59dbff9f1 refactor: standardize design
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
2026-03-03 21:55:48 -05:00

82 lines
2.2 KiB
TypeScript

/**
* useFileViewer — resolves which registered viewer can handle a given MIME type.
*
* Other modules register viewers at the `documents_file_viewer` integration
* point by including an entry in their `integrations.ts`:
*
* ```ts
* documents_file_viewer: [{
* id: 'my_viewer',
* meta: { mimeTypes: ['application/pdf'] },
* component: () => import('./components/MyViewer.vue'),
* }]
* ```
*
* Viewer components receive the props: `url: string`, `entity: EntityObject`, `mime: string`.
*/
import { useIntegrationStore } from '@KTXC'
import type { EntityObject } from '@DocumentsManager/models/entity'
const INTEGRATION_POINT = 'documents_file_viewer'
function mimeMatchesPattern(mime: string, pattern: string): boolean {
if (pattern.endsWith('/*')) {
// e.g. 'image/*' matches 'image/png', 'image/jpeg', …
return mime.startsWith(pattern.slice(0, -1))
}
return mime === pattern
}
function viewerMatchesMime(
mime: string,
mimeTypes?: string[],
mimePatterns?: string[],
): boolean {
if (mimeTypes?.includes(mime)) return true
if (mimePatterns) {
for (const pattern of mimePatterns) {
if (mimeMatchesPattern(mime, pattern)) return true
}
}
return false
}
export function useFileViewer() {
const integrationStore = useIntegrationStore()
/**
* Returns the highest-priority registered viewer that can handle `mime`,
* or `null` if none is found.
*/
function findViewer(mime: string) {
// getItems() already returns items sorted by priority (ascending)
const viewers = integrationStore.getItems(INTEGRATION_POINT)
for (const viewer of viewers) {
if (
viewerMatchesMime(
mime,
viewer.meta?.mimeTypes as string[] | undefined,
viewer.meta?.mimePatterns as string[] | undefined,
)
) {
return viewer
}
}
return null
}
/**
* Convenience: returns true if any registered viewer can open this entity.
*/
function canOpen(entity: EntityObject): boolean {
const mime = entity.properties.mime
if (!mime) return false
return findViewer(mime) !== null
}
return { findViewer, canOpen }
}
export type UseFileViewerReturn = ReturnType<typeof useFileViewer>