asset-viewer-nav-bar.svelte 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <script lang="ts">
  2. import { page } from '$app/stores';
  3. import { clickOutside } from '$lib/utils/click-outside';
  4. import type { AssetResponseDto } from '@api';
  5. import { createEventDispatcher } from 'svelte';
  6. import ArrowLeft from 'svelte-material-icons/ArrowLeft.svelte';
  7. import CloudDownloadOutline from 'svelte-material-icons/CloudDownloadOutline.svelte';
  8. import ContentCopy from 'svelte-material-icons/ContentCopy.svelte';
  9. import DeleteOutline from 'svelte-material-icons/DeleteOutline.svelte';
  10. import DotsVertical from 'svelte-material-icons/DotsVertical.svelte';
  11. import Heart from 'svelte-material-icons/Heart.svelte';
  12. import HeartOutline from 'svelte-material-icons/HeartOutline.svelte';
  13. import InformationOutline from 'svelte-material-icons/InformationOutline.svelte';
  14. import MagnifyPlusOutline from 'svelte-material-icons/MagnifyPlusOutline.svelte';
  15. import MagnifyMinusOutline from 'svelte-material-icons/MagnifyMinusOutline.svelte';
  16. import MotionPauseOutline from 'svelte-material-icons/MotionPauseOutline.svelte';
  17. import MotionPlayOutline from 'svelte-material-icons/MotionPlayOutline.svelte';
  18. import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
  19. import ContextMenu from '../shared-components/context-menu/context-menu.svelte';
  20. import MenuOption from '../shared-components/context-menu/menu-option.svelte';
  21. import { photoZoomState } from '$lib/stores/zoom-image.store';
  22. export let asset: AssetResponseDto;
  23. export let showCopyButton: boolean;
  24. export let showZoomButton: boolean;
  25. export let showMotionPlayButton: boolean;
  26. export let isMotionPhotoPlaying = false;
  27. export let showDownloadButton: boolean;
  28. const isOwner = asset.ownerId === $page.data.user?.id;
  29. const dispatch = createEventDispatcher();
  30. let contextMenuPosition = { x: 0, y: 0 };
  31. let isShowAssetOptions = false;
  32. const showOptionsMenu = ({ x, y }: MouseEvent) => {
  33. contextMenuPosition = { x, y };
  34. isShowAssetOptions = !isShowAssetOptions;
  35. };
  36. const onMenuClick = (eventName: string) => {
  37. isShowAssetOptions = false;
  38. dispatch(eventName);
  39. };
  40. </script>
  41. <div
  42. class="h-16 flex justify-between place-items-center px-3 transition-transform duration-200 z-[1001] bg-gradient-to-b from-black/40"
  43. >
  44. <div class="text-white">
  45. <CircleIconButton isOpacity={true} logo={ArrowLeft} on:click={() => dispatch('goBack')} />
  46. </div>
  47. <div class="text-white flex gap-2 justify-end w-[calc(100%-3rem)] overflow-hidden">
  48. {#if showMotionPlayButton}
  49. {#if isMotionPhotoPlaying}
  50. <CircleIconButton
  51. isOpacity={true}
  52. logo={MotionPauseOutline}
  53. title="Stop Motion Photo"
  54. on:click={() => dispatch('stopMotionPhoto')}
  55. />
  56. {:else}
  57. <CircleIconButton
  58. isOpacity={true}
  59. logo={MotionPlayOutline}
  60. title="Play Motion Photo"
  61. on:click={() => dispatch('playMotionPhoto')}
  62. />
  63. {/if}
  64. {/if}
  65. {#if showZoomButton}
  66. <CircleIconButton
  67. isOpacity={true}
  68. hideMobile={true}
  69. logo={$photoZoomState && $photoZoomState.currentZoom > 1 ? MagnifyMinusOutline : MagnifyPlusOutline}
  70. title="Zoom Image"
  71. on:click={() => {
  72. const zoomImage = new CustomEvent('zoomImage');
  73. window.dispatchEvent(zoomImage);
  74. }}
  75. />
  76. {/if}
  77. {#if showCopyButton}
  78. <CircleIconButton
  79. isOpacity={true}
  80. logo={ContentCopy}
  81. title="Copy Image"
  82. on:click={() => {
  83. const copyEvent = new CustomEvent('copyImage');
  84. window.dispatchEvent(copyEvent);
  85. }}
  86. />
  87. {/if}
  88. {#if showDownloadButton}
  89. <CircleIconButton
  90. isOpacity={true}
  91. logo={CloudDownloadOutline}
  92. on:click={() => dispatch('download')}
  93. title="Download"
  94. />
  95. {/if}
  96. <CircleIconButton isOpacity={true} logo={InformationOutline} on:click={() => dispatch('showDetail')} title="Info" />
  97. {#if isOwner}
  98. <CircleIconButton
  99. isOpacity={true}
  100. logo={asset.isFavorite ? Heart : HeartOutline}
  101. on:click={() => dispatch('favorite')}
  102. title="Favorite"
  103. />
  104. {/if}
  105. {#if isOwner}
  106. <CircleIconButton isOpacity={true} logo={DeleteOutline} on:click={() => dispatch('delete')} title="Delete" />
  107. <div use:clickOutside on:outclick={() => (isShowAssetOptions = false)}>
  108. <CircleIconButton isOpacity={true} logo={DotsVertical} on:click={showOptionsMenu} title="More">
  109. {#if isShowAssetOptions}
  110. <ContextMenu {...contextMenuPosition} direction="left">
  111. <MenuOption on:click={() => onMenuClick('addToAlbum')} text="Add to Album" />
  112. <MenuOption on:click={() => onMenuClick('addToSharedAlbum')} text="Add to Shared Album" />
  113. {#if isOwner}
  114. <MenuOption
  115. on:click={() => dispatch('toggleArchive')}
  116. text={asset.isArchived ? 'Unarchive' : 'Archive'}
  117. />
  118. {/if}
  119. </ContextMenu>
  120. {/if}
  121. </CircleIconButton>
  122. </div>
  123. {/if}
  124. </div>
  125. </div>