Explorar o código

feat(web): avoid duplicate call + small refactor (#1731)

Michel Heusschen %!s(int64=2) %!d(string=hai) anos
pai
achega
53fb3a36f7

+ 0 - 14
web/package-lock.json

@@ -17,7 +17,6 @@
 				"lodash-es": "^4.17.21",
 				"lodash-es": "^4.17.21",
 				"luxon": "^3.1.1",
 				"luxon": "^3.1.1",
 				"socket.io-client": "^4.5.1",
 				"socket.io-client": "^4.5.1",
-				"svelte-keydown": "^0.5.0",
 				"svelte-material-icons": "^2.0.2"
 				"svelte-material-icons": "^2.0.2"
 			},
 			},
 			"devDependencies": {
 			"devDependencies": {
@@ -54,7 +53,6 @@
 				"svelte": "^3.44.0",
 				"svelte": "^3.44.0",
 				"svelte-check": "^2.7.1",
 				"svelte-check": "^2.7.1",
 				"svelte-jester": "^2.3.2",
 				"svelte-jester": "^2.3.2",
-				"svelte-keydown": "^0.5.0",
 				"svelte-preprocess": "^4.10.7",
 				"svelte-preprocess": "^4.10.7",
 				"tailwindcss": "^3.0.24",
 				"tailwindcss": "^3.0.24",
 				"tslib": "^2.3.1",
 				"tslib": "^2.3.1",
@@ -10592,12 +10590,6 @@
 				"svelte": ">= 3"
 				"svelte": ">= 3"
 			}
 			}
 		},
 		},
-		"node_modules/svelte-keydown": {
-			"version": "0.5.0",
-			"resolved": "https://registry.npmjs.org/svelte-keydown/-/svelte-keydown-0.5.0.tgz",
-			"integrity": "sha512-DgY6AYlKbBocSvjC3kUeNPcStJQOTOCxAGG9ymVHzJdsQ1hRJuB8pcnB4UFH8uH3bAPdYyXXa3LwenLDL41eqQ==",
-			"dev": true
-		},
 		"node_modules/svelte-material-icons": {
 		"node_modules/svelte-material-icons": {
 			"version": "2.0.4",
 			"version": "2.0.4",
 			"resolved": "https://registry.npmjs.org/svelte-material-icons/-/svelte-material-icons-2.0.4.tgz",
 			"resolved": "https://registry.npmjs.org/svelte-material-icons/-/svelte-material-icons-2.0.4.tgz",
@@ -19031,12 +19023,6 @@
 			"dev": true,
 			"dev": true,
 			"requires": {}
 			"requires": {}
 		},
 		},
-		"svelte-keydown": {
-			"version": "0.5.0",
-			"resolved": "https://registry.npmjs.org/svelte-keydown/-/svelte-keydown-0.5.0.tgz",
-			"integrity": "sha512-DgY6AYlKbBocSvjC3kUeNPcStJQOTOCxAGG9ymVHzJdsQ1hRJuB8pcnB4UFH8uH3bAPdYyXXa3LwenLDL41eqQ==",
-			"dev": true
-		},
 		"svelte-material-icons": {
 		"svelte-material-icons": {
 			"version": "2.0.4",
 			"version": "2.0.4",
 			"resolved": "https://registry.npmjs.org/svelte-material-icons/-/svelte-material-icons-2.0.4.tgz",
 			"resolved": "https://registry.npmjs.org/svelte-material-icons/-/svelte-material-icons-2.0.4.tgz",

+ 0 - 2
web/package.json

@@ -52,7 +52,6 @@
 		"svelte": "^3.44.0",
 		"svelte": "^3.44.0",
 		"svelte-check": "^2.7.1",
 		"svelte-check": "^2.7.1",
 		"svelte-jester": "^2.3.2",
 		"svelte-jester": "^2.3.2",
-		"svelte-keydown": "^0.5.0",
 		"svelte-preprocess": "^4.10.7",
 		"svelte-preprocess": "^4.10.7",
 		"tailwindcss": "^3.0.24",
 		"tailwindcss": "^3.0.24",
 		"tslib": "^2.3.1",
 		"tslib": "^2.3.1",
@@ -70,7 +69,6 @@
 		"lodash-es": "^4.17.21",
 		"lodash-es": "^4.17.21",
 		"luxon": "^3.1.1",
 		"luxon": "^3.1.1",
 		"socket.io-client": "^4.5.1",
 		"socket.io-client": "^4.5.1",
-		"svelte-keydown": "^0.5.0",
 		"svelte-material-icons": "^2.0.2"
 		"svelte-material-icons": "^2.0.2"
 	}
 	}
 }
 }

+ 1 - 1
web/src/lib/components/asset-viewer/asset-viewer.svelte

@@ -304,7 +304,7 @@
 						on:onVideoEnded={() => (shouldPlayMotionPhoto = false)}
 						on:onVideoEnded={() => (shouldPlayMotionPhoto = false)}
 					/>
 					/>
 				{:else}
 				{:else}
-					<PhotoViewer {publicSharedKey} assetId={asset.id} on:close={closeViewer} />
+					<PhotoViewer {publicSharedKey} {asset} on:close={closeViewer} />
 				{/if}
 				{/if}
 			{:else}
 			{:else}
 				<VideoViewer {publicSharedKey} assetId={asset.id} on:close={closeViewer} />
 				<VideoViewer {publicSharedKey} assetId={asset.id} on:close={closeViewer} />

+ 37 - 46
web/src/lib/components/asset-viewer/photo-viewer.svelte

@@ -1,39 +1,21 @@
 <script lang="ts">
 <script lang="ts">
 	import { fade } from 'svelte/transition';
 	import { fade } from 'svelte/transition';
-
-	import { onMount } from 'svelte';
 	import LoadingSpinner from '../shared-components/loading-spinner.svelte';
 	import LoadingSpinner from '../shared-components/loading-spinner.svelte';
 	import { api, AssetResponseDto } from '@api';
 	import { api, AssetResponseDto } from '@api';
-	import Keydown from 'svelte-keydown';
+	import { copyImageToClipboard } from 'copy-image-clipboard';
 	import {
 	import {
 		notificationController,
 		notificationController,
 		NotificationType
 		NotificationType
 	} from '../shared-components/notification/notification';
 	} from '../shared-components/notification/notification';
 
 
-	export let assetId: string;
+	export let asset: AssetResponseDto;
 	export let publicSharedKey = '';
 	export let publicSharedKey = '';
 
 
-	let assetInfo: AssetResponseDto;
 	let assetData: string;
 	let assetData: string;
 
 
-	let copyImageToClipboard: (src: string) => Promise<Blob>;
-
-	onMount(async () => {
-		const { data } = await api.assetApi.getAssetById(assetId, {
-			params: {
-				key: publicSharedKey
-			}
-		});
-		assetInfo = data;
-
-		//Import hack :( see https://github.com/vadimkorr/svelte-carousel/issues/27#issuecomment-851022295
-		const module = await import('copy-image-clipboard');
-		copyImageToClipboard = module.copyImageToClipboard;
-	});
-
 	const loadAssetData = async () => {
 	const loadAssetData = async () => {
 		try {
 		try {
-			const { data } = await api.assetApi.serveFile(assetInfo.id, false, true, {
+			const { data } = await api.assetApi.serveFile(asset.id, false, true, {
 				params: {
 				params: {
 					key: publicSharedKey
 					key: publicSharedKey
 				},
 				},
@@ -51,42 +33,51 @@
 		}
 		}
 	};
 	};
 
 
-	const handleKeypress = async (keyEvent: CustomEvent<string>) => {
-		if (keyEvent.detail == 'Control-c' || keyEvent.detail == 'Meta-c') {
+	const handleKeypress = async ({ metaKey, ctrlKey, key }: KeyboardEvent) => {
+		if ((metaKey || ctrlKey) && key === 'c') {
 			await doCopy();
 			await doCopy();
 		}
 		}
 	};
 	};
 
 
 	export const doCopy = async () => {
 	export const doCopy = async () => {
-		await copyImageToClipboard(assetData);
-		notificationController.show({
-			type: NotificationType.Info,
-			message: 'Copied image to clipboard.',
-			timeout: 3000
-		});
+		try {
+			await copyImageToClipboard(assetData);
+			notificationController.show({
+				type: NotificationType.Info,
+				message: 'Copied image to clipboard.',
+				timeout: 3000
+			});
+		} catch (err) {
+			console.error(err);
+			notificationController.show({
+				type: NotificationType.Error,
+				message: 'Copying image to clipboard failed. Click here to learn more.',
+				timeout: 5000,
+				action: {
+					type: 'link',
+					target:
+						'https://github.com/LuanEdCosta/copy-image-clipboard#enable-clipboard-api-features-in-firefox'
+				}
+			});
+		}
 	};
 	};
 </script>
 </script>
 
 
-<Keydown on:combo={handleKeypress} />
-
-<svelte:window on:copyImage={async () => await doCopy()} />
+<svelte:window on:keydown={handleKeypress} on:copyImage={doCopy} />
 
 
 <div
 <div
 	transition:fade={{ duration: 150 }}
 	transition:fade={{ duration: 150 }}
 	class="flex place-items-center place-content-center h-full select-none"
 	class="flex place-items-center place-content-center h-full select-none"
 >
 >
-	{#if assetInfo}
-		{#await loadAssetData()}
-			<LoadingSpinner />
-		{:then assetData}
-			<img
-				transition:fade={{ duration: 150 }}
-				src={assetData}
-				alt={assetId}
-				class="object-contain h-full transition-all"
-				loading="lazy"
-				draggable="false"
-			/>
-		{/await}
-	{/if}
+	{#await loadAssetData()}
+		<LoadingSpinner />
+	{:then assetData}
+		<img
+			transition:fade={{ duration: 150 }}
+			src={assetData}
+			alt={asset.id}
+			class="object-contain h-full transition-all"
+			draggable="false"
+		/>
+	{/await}
 </div>
 </div>

+ 18 - 43
web/src/lib/components/asset-viewer/video-viewer.svelte

@@ -1,40 +1,17 @@
 <script lang="ts">
 <script lang="ts">
 	import { fade } from 'svelte/transition';
 	import { fade } from 'svelte/transition';
-
-	import { createEventDispatcher, onMount } from 'svelte';
+	import { createEventDispatcher } from 'svelte';
 	import LoadingSpinner from '../shared-components/loading-spinner.svelte';
 	import LoadingSpinner from '../shared-components/loading-spinner.svelte';
-	import { api, AssetResponseDto, getFileUrl } from '@api';
+	import { getFileUrl } from '@api';
 
 
 	export let assetId: string;
 	export let assetId: string;
 	export let publicSharedKey = '';
 	export let publicSharedKey = '';
-	let asset: AssetResponseDto;
 
 
 	let isVideoLoading = true;
 	let isVideoLoading = true;
-	let videoUrl: string;
 	const dispatch = createEventDispatcher();
 	const dispatch = createEventDispatcher();
 
 
-	onMount(async () => {
-		const { data: assetInfo } = await api.assetApi.getAssetById(assetId, {
-			params: {
-				key: publicSharedKey
-			}
-		});
-
-		await loadVideoData(assetInfo);
-
-		asset = assetInfo;
-	});
-
-	const loadVideoData = async (assetInfo: AssetResponseDto) => {
-		isVideoLoading = true;
-
-		videoUrl = getFileUrl(assetInfo.id, false, true, publicSharedKey);
-
-		return assetInfo;
-	};
-
-	const handleCanPlay = (ev: Event) => {
-		const playerNode = ev.target as HTMLVideoElement;
+	const handleCanPlay = (ev: Event & { currentTarget: HTMLVideoElement }) => {
+		const playerNode = ev.currentTarget;
 
 
 		playerNode.muted = true;
 		playerNode.muted = true;
 		playerNode.play();
 		playerNode.play();
@@ -48,21 +25,19 @@
 	transition:fade={{ duration: 150 }}
 	transition:fade={{ duration: 150 }}
 	class="flex place-items-center place-content-center h-full select-none"
 	class="flex place-items-center place-content-center h-full select-none"
 >
 >
-	{#if asset}
-		<video
-			controls
-			class="h-full object-contain"
-			on:canplay={handleCanPlay}
-			on:ended={() => dispatch('onVideoEnded')}
-		>
-			<source src={videoUrl} type="video/mp4" />
-			<track kind="captions" />
-		</video>
-
-		{#if isVideoLoading}
-			<div class="absolute flex place-items-center place-content-center">
-				<LoadingSpinner />
-			</div>
-		{/if}
+	<video
+		controls
+		class="h-full object-contain"
+		src={getFileUrl(assetId, false, true, publicSharedKey)}
+		on:canplay={handleCanPlay}
+		on:ended={() => dispatch('onVideoEnded')}
+	>
+		<track kind="captions" />
+	</video>
+
+	{#if isVideoLoading}
+		<div class="absolute flex place-items-center place-content-center">
+			<LoadingSpinner />
+		</div>
 	{/if}
 	{/if}
 </div>
 </div>