feat(web): loop videos
This commit is contained in:
parent
e1e45f3f32
commit
2c8bc9bccf
8 changed files with 66 additions and 5 deletions
|
@ -23,6 +23,7 @@
|
|||
import { createEventDispatcher } from 'svelte';
|
||||
import ContextMenu from '../shared-components/context-menu/context-menu.svelte';
|
||||
import MenuOption from '../shared-components/context-menu/menu-option.svelte';
|
||||
import { shouldLoopVideo } from '$lib/stores/assets.store';
|
||||
|
||||
export let asset: AssetResponseDto;
|
||||
export let showCopyButton: boolean;
|
||||
|
@ -36,7 +37,14 @@
|
|||
|
||||
$: isOwner = asset.ownerId === $page.data.user?.id;
|
||||
|
||||
type MenuItemEvent = 'addToAlbum' | 'addToSharedAlbum' | 'asProfileImage' | 'runJob' | 'playSlideShow' | 'unstack';
|
||||
type MenuItemEvent =
|
||||
| 'addToAlbum'
|
||||
| 'addToSharedAlbum'
|
||||
| 'asProfileImage'
|
||||
| 'runJob'
|
||||
| 'playSlideShow'
|
||||
| 'unstack'
|
||||
| 'loopVideo';
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
goBack: void;
|
||||
|
@ -53,6 +61,7 @@
|
|||
runJob: AssetJobName;
|
||||
playSlideShow: void;
|
||||
unstack: void;
|
||||
loopVideo: void;
|
||||
}>();
|
||||
|
||||
let contextMenuPosition = { x: 0, y: 0 };
|
||||
|
@ -168,7 +177,9 @@
|
|||
{/if}
|
||||
<MenuOption on:click={() => onMenuClick('addToAlbum')} text="Add to Album" />
|
||||
<MenuOption on:click={() => onMenuClick('addToSharedAlbum')} text="Add to Shared Album" />
|
||||
|
||||
{#if asset.type === AssetTypeEnum.Video}
|
||||
<MenuOption on:click={() => onMenuClick('loopVideo')} text="Loop video" checked={$shouldLoopVideo} />
|
||||
{/if}
|
||||
{#if isOwner}
|
||||
<MenuOption
|
||||
on:click={() => dispatch('toggleArchive')}
|
||||
|
|
|
@ -23,12 +23,12 @@
|
|||
import { ProjectionType } from '$lib/constants';
|
||||
import ConfirmDialogue from '$lib/components/shared-components/confirm-dialogue.svelte';
|
||||
import ProfileImageCropper from '../shared-components/profile-image-cropper.svelte';
|
||||
import { isShowDetail } from '$lib/stores/preferences.store';
|
||||
import { isShowDetail, loopVideoSetting } from '$lib/stores/preferences.store';
|
||||
import { addAssetsToAlbum, downloadFile, getAssetType } from '$lib/utils/asset-utils';
|
||||
import NavigationArea from './navigation-area.svelte';
|
||||
import { browser } from '$app/environment';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import type { AssetStore } from '$lib/stores/assets.store';
|
||||
import { changeShouldLoopVideo, type AssetStore, shouldLoopVideo } from '$lib/stores/assets.store';
|
||||
import { shouldIgnoreShortcut } from '$lib/utils/shortcut';
|
||||
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
|
||||
import { SlideshowHistory } from '$lib/utils/slideshow-history';
|
||||
|
@ -96,6 +96,8 @@
|
|||
let isLiked: ActivityResponseDto | null = null;
|
||||
let numberOfComments: number;
|
||||
|
||||
$: asset.id && asset.type === AssetTypeEnum.Video && changeShouldLoopVideo($loopVideoSetting);
|
||||
|
||||
$: {
|
||||
if (asset.stackCount && asset.stack) {
|
||||
$stackAssetsStore = asset.stack;
|
||||
|
@ -590,6 +592,7 @@
|
|||
on:runJob={({ detail: job }) => handleRunJob(job)}
|
||||
on:playSlideShow={() => ($slideshowState = SlideshowState.PlaySlideshow)}
|
||||
on:unstack={handleUnstack}
|
||||
on:loopVideo={() => changeShouldLoopVideo(!$shouldLoopVideo)}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
import { videoViewerVolume } from '$lib/stores/preferences.store';
|
||||
import LoadingSpinner from '../shared-components/loading-spinner.svelte';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { shouldLoopVideo } from '$lib/stores/assets.store';
|
||||
|
||||
export let assetId: string;
|
||||
|
||||
|
@ -31,6 +32,7 @@
|
|||
autoplay
|
||||
playsinline
|
||||
controls
|
||||
loop={$shouldLoopVideo}
|
||||
class="h-full object-contain"
|
||||
on:canplay={handleCanPlay}
|
||||
on:ended={() => dispatch('onVideoEnded')}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
<script>
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { mdiCheck } from '@mdi/js';
|
||||
|
||||
export let text = '';
|
||||
export let subtitle = '';
|
||||
export let checked = false;
|
||||
</script>
|
||||
|
||||
<button
|
||||
|
@ -9,7 +13,16 @@
|
|||
role="menuitem"
|
||||
>
|
||||
{#if text}
|
||||
<div class="flex">
|
||||
<div class="w-full">
|
||||
{text}
|
||||
</div>
|
||||
{#if checked}
|
||||
<div>
|
||||
<Icon path={mdiCheck} />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<slot />
|
||||
{/if}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<script lang="ts">
|
||||
import { fade } from 'svelte/transition';
|
||||
import SettingSwitch from '../admin-page/settings/setting-switch.svelte';
|
||||
import { loopVideoSetting } from '$lib/stores/preferences.store';
|
||||
</script>
|
||||
|
||||
<section class="my-4">
|
||||
<div in:fade={{ duration: 500 }}>
|
||||
<div class="ml-4 mt-4 flex flex-col gap-4">
|
||||
<div class="ml-4">
|
||||
<SettingSwitch
|
||||
title="Loop videos"
|
||||
subtitle="Enable automatically loop videos."
|
||||
bind:checked={$loopVideoSetting}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
|
@ -13,6 +13,7 @@
|
|||
import SidebarSettings from './sidebar-settings.svelte';
|
||||
import UserAPIKeyList from './user-api-key-list.svelte';
|
||||
import UserProfileSettings from './user-profile-settings.svelte';
|
||||
import AssetSettings from './asset-settings.svelte';
|
||||
|
||||
export let user: UserResponseDto;
|
||||
|
||||
|
@ -67,3 +68,7 @@
|
|||
<SettingAccordion title="Sidebar" subtitle="Manage sidebar settings">
|
||||
<SidebarSettings />
|
||||
</SettingAccordion>
|
||||
|
||||
<SettingAccordion title="Viewing experience" subtitle="Manage the browsing experience">
|
||||
<AssetSettings />
|
||||
</SettingAccordion>
|
||||
|
|
|
@ -415,3 +415,9 @@ export class AssetStore {
|
|||
this.store$.update(() => this);
|
||||
}
|
||||
}
|
||||
|
||||
export const shouldLoopVideo = writable<boolean>();
|
||||
|
||||
export const changeShouldLoopVideo = (value: boolean) => {
|
||||
shouldLoopVideo.set(value);
|
||||
};
|
||||
|
|
|
@ -67,3 +67,5 @@ export const albumViewSettings = persisted<AlbumViewSettings>('album-view-settin
|
|||
sortDesc: true,
|
||||
view: AlbumViewMode.Cover,
|
||||
});
|
||||
|
||||
export const loopVideoSetting = persisted<boolean>('loop-video', false, {});
|
||||
|
|
Loading…
Reference in a new issue