|
5 | 5 | <v-container v-if="isLoading" class="fill-height flex-column justify-center align-center mt-n16">
|
6 | 6 | <v-progress-circular indeterminate />
|
7 | 7 | </v-container>
|
8 |
| - <v-container v-else-if="previewIsVideo" class="fill-height flex-column justify-center align-center"> |
| 8 | + <v-container v-else-if="previewType === PreviewType.Video" class="fill-height flex-column justify-center align-center"> |
9 | 9 | <video
|
10 | 10 | controls
|
11 | 11 | :src="objectPreviewUrl"
|
12 | 12 | style="max-width: 100%; max-height: 90%;"
|
13 | 13 | aria-roledescription="video-preview"
|
14 | 14 | />
|
15 | 15 | </v-container>
|
16 |
| - <v-container v-else-if="previewIsAudio" class="fill-height flex-column justify-center align-center"> |
| 16 | + <v-container v-else-if="previewType === PreviewType.Audio" class="fill-height flex-column justify-center align-center"> |
17 | 17 | <audio
|
18 | 18 | controls
|
19 | 19 | :src="objectPreviewUrl"
|
20 | 20 | aria-roledescription="audio-preview"
|
21 | 21 | />
|
22 | 22 | </v-container>
|
23 |
| - <v-container v-else-if="previewIsImage" class="fill-height flex-column justify-center align-center"> |
| 23 | + <v-container v-else-if="previewType === PreviewType.Image" class="fill-height flex-column justify-center align-center"> |
24 | 24 | <img
|
25 | 25 | v-if="objectPreviewUrl"
|
26 | 26 | :src="objectPreviewUrl"
|
|
29 | 29 | alt="preview"
|
30 | 30 | >
|
31 | 31 | </v-container>
|
32 |
| - <v-container v-else-if="placeHolderDisplayable || previewAndMapFailed" class="fill-height flex-column justify-center align-center mt-n16"> |
33 |
| - <p class="mb-5">{{ file?.Key || '' }}</p> |
34 |
| - <p class="text-h5 mb-5 font-weight-bold">No preview available</p> |
35 |
| - <v-btn |
36 |
| - @click="() => emits('download')" |
| 32 | + <v-container v-else-if="previewType === PreviewType.PDF" class="fill-height flex-column justify-center align-center"> |
| 33 | + <object |
| 34 | + :data="objectPreviewUrl" |
| 35 | + type="application/pdf" |
| 36 | + aria-roledescription="pdf-preview" |
| 37 | + class="h-100 w-100" |
37 | 38 | >
|
38 |
| - <template #prepend> |
39 |
| - <img src="@poc/assets/icon-download.svg" width="22" alt="Download"> |
40 |
| - </template> |
41 |
| - {{ `Download (${prettyBytes(file?.Size || 0)})` }} |
42 |
| - </v-btn> |
| 39 | + <file-preview-placeholder :file="file" @download="emit('download')" /> |
| 40 | + </object> |
43 | 41 | </v-container>
|
| 42 | + <file-preview-placeholder v-else class="mt-n16" :file="file" @download="emit('download')" /> |
44 | 43 | </template>
|
45 | 44 |
|
46 | 45 | <script setup lang="ts">
|
47 | 46 | import { computed, ref, watch } from 'vue';
|
48 |
| -import { VBtn, VContainer, VProgressCircular } from 'vuetify/components'; |
49 |
| -import { useRoute } from 'vue-router'; |
50 |
| -import prettyBytes from 'pretty-bytes'; |
| 47 | +import { VContainer, VProgressCircular } from 'vuetify/components'; |
51 | 48 |
|
52 |
| -import { useAppStore } from '@/store/modules/appStore'; |
53 | 49 | import { BrowserObject, PreviewCache, useObjectBrowserStore } from '@/store/modules/objectBrowserStore';
|
54 | 50 | import { useBucketsStore } from '@/store/modules/bucketsStore';
|
55 | 51 | import { useNotify } from '@/utils/hooks';
|
56 | 52 | import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
|
57 | 53 | import { useLinksharing } from '@/composables/useLinksharing';
|
58 | 54 |
|
59 |
| -const appStore = useAppStore(); |
| 55 | +import FilePreviewPlaceholder from '@poc/components/dialogs/filePreviewComponents/FilePreviewPlaceholder.vue'; |
| 56 | +
|
| 57 | +enum PreviewType { |
| 58 | + None, |
| 59 | + Image, |
| 60 | + Video, |
| 61 | + Audio, |
| 62 | + PDF, |
| 63 | +} |
| 64 | +
|
60 | 65 | const obStore = useObjectBrowserStore();
|
61 | 66 | const bucketsStore = useBucketsStore();
|
62 | 67 | const notify = useNotify();
|
63 | 68 | const { generateObjectPreviewAndMapURL } = useLinksharing();
|
64 | 69 |
|
65 |
| -const route = useRoute(); |
66 |
| -
|
67 | 70 | const isLoading = ref<boolean>(false);
|
68 | 71 | const previewAndMapFailed = ref<boolean>(false);
|
69 | 72 |
|
70 |
| -const imgExts = ['bmp', 'svg', 'jpg', 'jpeg', 'png', 'ico', 'gif']; |
71 |
| -const videoExts = ['m4v', 'mp4', 'webm', 'mov', 'mkv']; |
72 |
| -const audioExts = ['m4a', 'mp3', 'wav', 'ogg']; |
| 73 | +const extInfos = new Map<string[], PreviewType>([ |
| 74 | + [['bmp', 'svg', 'jpg', 'jpeg', 'png', 'ico', 'gif'], PreviewType.Image], |
| 75 | + [['m4v', 'mp4', 'webm', 'mov', 'mkv'], PreviewType.Video], |
| 76 | + [['m4a', 'mp3', 'wav', 'ogg'], PreviewType.Audio], |
| 77 | + [['pdf'], PreviewType.PDF], |
| 78 | +]); |
73 | 79 |
|
74 | 80 | const props = defineProps<{
|
75 | 81 | file: BrowserObject,
|
76 | 82 | active: boolean, // whether this item is visible
|
77 | 83 | }>();
|
78 | 84 |
|
79 |
| -const emits = defineEmits(['download']); |
| 85 | +const emit = defineEmits<{ |
| 86 | + download: []; |
| 87 | +}>(); |
80 | 88 |
|
81 | 89 | /**
|
82 | 90 | * Returns object preview URLs cache from store.
|
@@ -109,54 +117,20 @@ const encodedFilePath = computed((): string => {
|
109 | 117 | });
|
110 | 118 |
|
111 | 119 | /**
|
112 |
| - * Get the extension of the current file. |
113 |
| - */ |
114 |
| -const extension = computed((): string | undefined => { |
115 |
| - return props.file.Key.split('.').pop(); |
116 |
| -}); |
117 |
| -
|
118 |
| -/** |
119 |
| - * Check to see if the current file is an image file. |
| 120 | + * Returns the type of object being previewed. |
120 | 121 | */
|
121 |
| -const previewIsImage = computed((): boolean => { |
122 |
| - if (!extension.value) { |
123 |
| - return false; |
124 |
| - } |
| 122 | +const previewType = computed<PreviewType>(() => { |
| 123 | + if (previewAndMapFailed.value) return PreviewType.None; |
125 | 124 |
|
126 |
| - return imgExts.includes(extension.value.toLowerCase()); |
127 |
| -}); |
| 125 | + const dotIdx = props.file.Key.lastIndexOf('.'); |
| 126 | + if (dotIdx === -1) return PreviewType.None; |
128 | 127 |
|
129 |
| -/** |
130 |
| - * Check to see if the current file is a video file. |
131 |
| - */ |
132 |
| -const previewIsVideo = computed((): boolean => { |
133 |
| - if (!extension.value) { |
134 |
| - return false; |
| 128 | + const ext = props.file.Key.toLowerCase().slice(dotIdx + 1); |
| 129 | + for (const [exts, previewType] of extInfos) { |
| 130 | + if (exts.includes(ext)) return previewType; |
135 | 131 | }
|
136 | 132 |
|
137 |
| - return videoExts.includes(extension.value.toLowerCase()); |
138 |
| -}); |
139 |
| -
|
140 |
| -/** |
141 |
| - * Check to see if the current file is an audio file. |
142 |
| - */ |
143 |
| -const previewIsAudio = computed((): boolean => { |
144 |
| - if (!extension.value) { |
145 |
| - return false; |
146 |
| - } |
147 |
| -
|
148 |
| - return audioExts.includes(extension.value.toLowerCase()); |
149 |
| -}); |
150 |
| -
|
151 |
| -/** |
152 |
| - * Check to see if the current file is neither an image file, video file, or audio file. |
153 |
| - */ |
154 |
| -const placeHolderDisplayable = computed((): boolean => { |
155 |
| - return [ |
156 |
| - previewIsImage.value, |
157 |
| - previewIsVideo.value, |
158 |
| - previewIsAudio.value, |
159 |
| - ].every((value) => !value); |
| 133 | + return PreviewType.None; |
160 | 134 | });
|
161 | 135 |
|
162 | 136 | /**
|
|
0 commit comments