/** * mediaViewer — bridges the Mail UI to the standalone media_viewer module */ import { defineAsyncComponent } from 'vue' import { useIntegrationStore } from '@KTXC' const MEDIA_VIEWER_FORMAT_POINT = 'media_viewer_format' const MEDIA_VIEWER_POINT = 'media_viewer' function mimeMatchesPattern(mime: string, pattern: string): boolean { if (pattern.endsWith('/*')) { return mime.startsWith(pattern.slice(0, -1)) } return mime === pattern } function mimeMatchesViewer(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 } /** True if a leaf viewer is registered for this MIME type. */ export function mediaViewerCanDisplay(mime: string | null | undefined): boolean { if (!mime) return false const viewers = useIntegrationStore().getItems(MEDIA_VIEWER_FORMAT_POINT) return viewers.some(viewer => mimeMatchesViewer( mime, viewer.meta?.mimeTypes as string[] | undefined, viewer.meta?.mimePatterns as string[] | undefined, ), ) } export function mediaViewerComponent(type: 'dialog' | 'popover' = 'dialog') { // The integration store prefixes ids with the module handle // (e.g. 'media_viewer.dialog'), so match on the suffix. const entry = useIntegrationStore().getItems(MEDIA_VIEWER_POINT).find(i => i.id.endsWith(`.${type}`)) return entry?.component ? defineAsyncComponent(entry.component as () => Promise) : null }