useImageViewer.ts 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. import { canPreviewFile } from '#shared/utils/files.ts'
  3. import type { MaybeRef } from '@vueuse/shared'
  4. import { ref, unref, watchEffect } from 'vue'
  5. interface ImagePreview {
  6. src?: string
  7. title?: string
  8. }
  9. export interface ImageViewerFile {
  10. name?: string
  11. content?: string
  12. preview?: string
  13. inline?: string
  14. type?: Maybe<string>
  15. }
  16. export interface ViewerOptions {
  17. images: ImagePreview[]
  18. index: number
  19. visible: boolean
  20. }
  21. export const imageViewerOptions = ref<ViewerOptions>({
  22. visible: false,
  23. index: 0,
  24. images: [],
  25. })
  26. const useImageViewer = (viewFiles: MaybeRef<ImageViewerFile[]>) => {
  27. const indexMap = new WeakMap<ImageViewerFile, number>()
  28. let images: ImagePreview[] = []
  29. watchEffect(() => {
  30. images = unref(viewFiles)
  31. .filter((file) => canPreviewFile(file.type))
  32. .map((image, index) => {
  33. // we need to keep track of indexes, because they might
  34. // be different from original files, if they had non-image uploads
  35. indexMap.set(image, index)
  36. return {
  37. src: image.inline || image.preview || image.content,
  38. title: image.name,
  39. }
  40. })
  41. })
  42. const showImage = (image: ImageViewerFile) => {
  43. const foundIndex = indexMap.get(image) ?? 0
  44. imageViewerOptions.value = {
  45. index: foundIndex,
  46. images,
  47. visible: true,
  48. }
  49. }
  50. const hideImage = () => {
  51. imageViewerOptions.value = {
  52. images: [],
  53. index: 0,
  54. visible: false,
  55. }
  56. }
  57. const isViewable = (file: ImageViewerFile) => indexMap.has(file)
  58. return {
  59. isViewable,
  60. showImage,
  61. hideImage,
  62. }
  63. }
  64. export { useImageViewer }