a59dbff9f1
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
82 lines
2.2 KiB
TypeScript
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>
|