11<script setup lang="ts">
2- import { ref , onMounted , onUnmounted , computed , watch , nextTick , type Component } from ' vue'
2+ import { ref , onMounted , onUnmounted , computed , watch , nextTick , markRaw , type Component } from ' vue'
33import { useRouter } from ' vue-router'
4+ import { type Session } from ' xconn'
45
56import { useMachinesStore } from ' @/stores/machines'
67import { useSettingsStore } from ' @/stores/settings'
@@ -11,9 +12,11 @@ import EmbeddedIndexedFiles from '@/components/EmbeddedIndexedFiles.vue'
1112import TerminalPanel from ' @/components/TerminalPanel.vue'
1213import ResourceMonitor from ' @/components/ResourceMonitor.vue'
1314import DesktopSettingsPanel from ' @/components/DesktopSettingsPanel.vue'
15+ import FilePreviewModal from ' @/components/FilePreviewModal.vue'
1416import FloatingWindow from ' @/components/FloatingWindow.vue'
1517import AppDock from ' @/components/AppDock.vue'
1618import { loadCachedWallpaper , storeWallpaper } from ' @/composables/useWallpaperCache'
19+ import { getFilePreviewType , type FilePreviewType } from ' @/utils/fileTypes'
1720
1821const props = defineProps <{ realm: string ; active: boolean }>()
1922
@@ -37,6 +40,7 @@ const {
3740 restoreWindow,
3841 toggleMaximize,
3942 updateBounds,
43+ updateTitle,
4044 syncMaximizedBounds,
4145} = desktopSessionsStore .getOrCreate (props .realm )
4246
@@ -207,6 +211,7 @@ const appComponents: Record<string, Component> = {
207211 documents: EmbeddedIndexedFiles ,
208212 ' resource-monitor' : ResourceMonitor ,
209213 settings: DesktopSettingsPanel ,
214+ preview: FilePreviewModal ,
210215}
211216
212217function windowProps(win : { id: string ; appId: string ; props: Record <string , unknown > }) {
@@ -237,6 +242,13 @@ function windowProps(win: { id: string; appId: string; props: Record<string, unk
237242 realm: props .realm ,
238243 focused ,
239244 }
245+ case ' preview' :
246+ return {
247+ session: win .props .session as Session ,
248+ entry: win .props .entry as PreviewEntry ,
249+ entries: win .props .entries as PreviewEntry [],
250+ focused ,
251+ }
240252 default :
241253 return {
242254 realm: props .realm ,
@@ -247,6 +259,30 @@ function windowProps(win: { id: string; appId: string; props: Record<string, unk
247259 }
248260}
249261
262+ type PreviewEntry = { path: string ; name: string ; size: number }
263+
264+ const PREVIEW_ICONS: Record <FilePreviewType , string > = {
265+ image: ' bi-image-fill' ,
266+ video: ' bi-file-earmark-play-fill' ,
267+ audio: ' bi-file-earmark-music-fill' ,
268+ pdf: ' bi-file-earmark-pdf-fill' ,
269+ text: ' bi-file-earmark-text-fill' ,
270+ none: ' bi-file-earmark-fill' ,
271+ }
272+
273+ function onPreviewFile(session : Session , entry : PreviewEntry , entries : PreviewEntry []) {
274+ openWindow ({
275+ appId: ' preview' ,
276+ title: entry .name ,
277+ icon: PREVIEW_ICONS [getFilePreviewType (entry .name )],
278+ iconColor: ' #334155' ,
279+ iconBg: ' #e2e8f0' ,
280+ width: 760 ,
281+ height: 560 ,
282+ props: { session: markRaw (session ), entry , entries },
283+ }, maximizedContainerSize ())
284+ }
285+
250286function onOpenFiles(path : string ) {
251287 const filesApp = apps .find ((a ) => a .id === ' files' )!
252288 launchApp (filesApp , path )
@@ -382,6 +418,8 @@ onUnmounted(() => {
382418 v-bind =" windowProps(win)"
383419 @close =" closeWindow(win.id)"
384420 @open-files =" onOpenFiles"
421+ @preview-file =" onPreviewFile"
422+ @update-title =" updateTitle(win.id, $event)"
385423 />
386424 </FloatingWindow >
387425 </div >
0 commit comments