Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(web): configure slideshow #7219

Merged
merged 9 commits into from
Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@
desc="Minimum confidence score for a face to be detected from 0-1. Lower values will detect more faces but may result in false positives."
bind:value={config.machineLearning.facialRecognition.minScore}
step="0.1"
min="0"
max="1"
min={0}
max={1}
disabled={disabled || !config.machineLearning.enabled || !config.machineLearning.facialRecognition.enabled}
isEdited={config.machineLearning.facialRecognition.minScore !==
savedConfig.machineLearning.facialRecognition.minScore}
Expand All @@ -125,8 +125,8 @@
desc="Maximum distance between two faces to be considered the same person, ranging from 0-2. Lowering this can prevent labeling two people as the same person, while raising it can prevent labeling the same person as two different people. Note that it is easier to merge two people than to split one person in two, so err on the side of a lower threshold when possible."
bind:value={config.machineLearning.facialRecognition.maxDistance}
step="0.1"
min="0"
max="2"
min={0}
max={2}
disabled={disabled || !config.machineLearning.enabled || !config.machineLearning.facialRecognition.enabled}
isEdited={config.machineLearning.facialRecognition.maxDistance !==
savedConfig.machineLearning.facialRecognition.maxDistance}
Expand All @@ -138,7 +138,7 @@
desc="The minimum number of recognized faces for a person to be created. Increasing this makes Facial Recognition more precise at the cost of increasing the chance that a face is not assigned to a person."
bind:value={config.machineLearning.facialRecognition.minFaces}
step="1"
min="1"
min={1}
disabled={disabled || !config.machineLearning.enabled || !config.machineLearning.facialRecognition.enabled}
isEdited={config.machineLearning.facialRecognition.minFaces !==
savedConfig.machineLearning.facialRecognition.minFaces}
Expand Down
39 changes: 17 additions & 22 deletions web/src/lib/components/asset-viewer/slideshow-bar.svelte
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
<script lang="ts">
import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
import ProgressBar, { ProgressBarStatus } from '../shared-components/progress-bar/progress-bar.svelte';
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
import ProgressBar, { ProgressBarStatus } from '$lib/components/shared-components/progress-bar/progress-bar.svelte';
import SlideshowSettings from '$lib/components/slideshow-settings.svelte';
import { slideshowStore } from '$lib/stores/slideshow.store';
import { mdiChevronLeft, mdiChevronRight, mdiClose, mdiCog, mdiPause, mdiPlay } from '@mdi/js';
import { createEventDispatcher, onDestroy, onMount } from 'svelte';
import {
mdiChevronLeft,
mdiChevronRight,
mdiClose,
mdiPause,
mdiPlay,
mdiShuffle,
mdiShuffleDisabled,
} from '@mdi/js';

const { slideshowShuffle } = slideshowStore;
const { restartProgress, stopProgress } = slideshowStore;
const { restartProgress, stopProgress, slideshowDelay, showProgressBar } = slideshowStore;

let progressBarStatus: ProgressBarStatus;
let progressBar: ProgressBar;
let showSettings = false;

let unsubscribeRestart: () => void;
let unsubscribeStop: () => void;
Expand Down Expand Up @@ -54,25 +47,27 @@
</script>

<div class="m-4 flex gap-2">
<CircleIconButton icon={mdiClose} on:click={() => dispatch('close')} title="Exit Slideshow" />
{#if $slideshowShuffle}
<CircleIconButton icon={mdiShuffle} on:click={() => ($slideshowShuffle = false)} title="Shuffle" />
{:else}
<CircleIconButton icon={mdiShuffleDisabled} on:click={() => ($slideshowShuffle = true)} title="No shuffle" />
{/if}
<CircleIconButton buttonSize="50" icon={mdiClose} on:click={() => dispatch('close')} title="Exit Slideshow" />
<CircleIconButton
buttonSize="50"
icon={progressBarStatus === ProgressBarStatus.Paused ? mdiPlay : mdiPause}
on:click={() => (progressBarStatus === ProgressBarStatus.Paused ? progressBar.play() : progressBar.pause())}
title={progressBarStatus === ProgressBarStatus.Paused ? 'Play' : 'Pause'}
/>
<CircleIconButton icon={mdiChevronLeft} on:click={() => dispatch('prev')} title="Previous" />
<CircleIconButton icon={mdiChevronRight} on:click={() => dispatch('next')} title="Next" />
<CircleIconButton buttonSize="50" icon={mdiChevronLeft} on:click={() => dispatch('prev')} title="Previous" />
<CircleIconButton buttonSize="50" icon={mdiChevronRight} on:click={() => dispatch('next')} title="Next" />
<CircleIconButton buttonSize="50" icon={mdiCog} on:click={() => (showSettings = !showSettings)} title="Next" />
</div>

{#if showSettings}
<SlideshowSettings onClose={() => (showSettings = false)} />
{/if}

<ProgressBar
autoplay
hidden={!$showProgressBar}
duration={$slideshowDelay}
bind:this={progressBar}
bind:status={progressBarStatus}
on:done={() => dispatch('next')}
duration={5000}
/>
72 changes: 72 additions & 0 deletions web/src/lib/components/elements/slider.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte';

export let checked = false;
export let disabled = false;

const dispatch = createEventDispatcher<{ toggle: boolean }>();
const onToggle = (event: Event) => dispatch('toggle', (event.target as HTMLInputElement).checked);
</script>

<label class="relative inline-block h-[10px] w-[36px] flex-none">
<input
class="disabled::cursor-not-allowed h-0 w-0 opacity-0"
type="checkbox"
bind:checked
on:click={onToggle}
{disabled}
/>

{#if disabled}
<span class="slider slider-disabled cursor-not-allowed" />
{:else}
<span class="slider slider-enabled cursor-pointer" />
{/if}
</label>

<style>
.slider {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: 0.4s;
transition: 0.4s;
border-radius: 34px;
}

input:disabled {
cursor: not-allowed;
}

.slider:before {
position: absolute;
content: '';
height: 20px;
width: 20px;
left: 0px;
right: 0px;
bottom: -4px;
background-color: gray;
-webkit-transition: 0.4s;
transition: 0.4s;
border-radius: 50%;
}

input:checked + .slider:before {
-webkit-transform: translateX(18px);
-ms-transform: translateX(18px);
transform: translateX(18px);
background-color: #4250af;
}

input:checked + .slider-disabled {
background-color: gray;
}

input:checked + .slider-enabled {
background-color: #adcbfa;
}
</style>
6 changes: 3 additions & 3 deletions web/src/lib/components/photos-page/asset-grid.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -456,9 +456,9 @@
asset={$viewingAsset}
{isShared}
{album}
on:previous={() => handlePrevious()}
on:next={() => handleNext()}
on:close={() => handleClose()}
on:previous={handlePrevious}
on:next={handleNext}
on:close={handleClose}
on:action={({ detail: action }) => handleAction(action.type, action.asset)}
/>
{/if}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,29 @@
*/
export let autoplay = false;

/**
* Duration in milliseconds
* @default 5000
*/
export let duration = 5000;

/**
* Progress bar status
*/
export let status: ProgressBarStatus = ProgressBarStatus.Paused;

let progress = tweened<number>(0, {
duration: (from: number, to: number) => (to ? duration * (to - from) : 0),
});
export let hidden = false;

export let duration = 5;

const onChange = () => {
progress = setDuration(duration);
play();
};

let progress = setDuration(duration);

$: duration, onChange();

$: {
if ($progress === 1) {
dispatch('done');
}
}

const dispatch = createEventDispatcher<{
done: void;
Expand Down Expand Up @@ -67,17 +76,13 @@
progress.set(0);
};

export const setDuration = (newDuration: number) => {
progress = tweened<number>(0, {
duration: (from: number, to: number) => (to ? newDuration * (to - from) : 0),
function setDuration(newDuration: number) {
return tweened<number>(0, {
duration: (from: number, to: number) => (to ? newDuration * 1000 * (to - from) : 0),
});
};

progress.subscribe((value) => {
if (value === 1) {
dispatch('done');
}
});
}
</script>

<span class="absolute left-0 h-[3px] bg-immich-primary shadow-2xl" style:width={`${$progress * 100}%`} />
{#if !hidden}
<span class="absolute left-0 h-[3px] bg-immich-primary shadow-2xl" style:width={`${$progress * 100}%`} />
{/if}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@

export let inputType: SettingInputFieldType;
export let value: string | number;
export let min = Number.MIN_SAFE_INTEGER.toString();
export let max = Number.MAX_SAFE_INTEGER.toString();
export let min = Number.MIN_SAFE_INTEGER;
export let max = Number.MAX_SAFE_INTEGER;
export let step = '1';
export let label = '';
export let desc = '';
Expand All @@ -25,15 +25,23 @@

const handleInput = (e: Event) => {
value = (e.target as HTMLInputElement).value;

if (inputType === SettingInputFieldType.NUMBER) {
value = Number(value) || 0;
let newValue = Number(value) || 0;
if (newValue < min) {
newValue = min;
}
if (newValue > max) {
newValue = max;
}
value = newValue;
}
};
</script>

<div class="mb-4 w-full">
<div class={`flex h-[26px] place-items-center gap-1`}>
<label class={`immich-form-label text-sm`} for={label}>{label}</label>
<label class="font-medium text-immich-primary dark:text-immich-dark-primary text-sm" for={label}>{label}</label>
{#if required}
<div class="text-red-400">*</div>
{/if}
Expand Down Expand Up @@ -63,8 +71,8 @@
id={label}
name={label}
type={inputType}
{min}
{max}
min={min.toString()}
max={max.toString()}
{step}
{required}
{value}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@

<div class="mb-4 w-full">
<div class={`flex h-[26px] place-items-center gap-1`}>
<label class={`immich-form-label text-sm`} for="{name}-select">{label}</label>
<label class="font-medium text-immich-primary dark:text-immich-dark-primary text-sm" for="{name}-select"
>{label}</label
>

{#if isEdited}
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { quintOut } from 'svelte/easing';
import { fly } from 'svelte/transition';
import { createEventDispatcher } from 'svelte';
import Slider from '$lib/components/elements/slider.svelte';

export let title: string;
export let subtitle = '';
Expand Down Expand Up @@ -33,66 +34,5 @@
<slot />
</div>

<label class="relative inline-block h-[10px] w-[36px] flex-none">
<input
class="disabled::cursor-not-allowed h-0 w-0 opacity-0"
type="checkbox"
bind:checked
on:click={onToggle}
{disabled}
/>

{#if disabled}
<span class="slider slider-disabled cursor-not-allowed" />
{:else}
<span class="slider slider-enabled cursor-pointer" />
{/if}
</label>
<Slider bind:checked {disabled} on:click={onToggle} />
</div>

<style>
.slider {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: 0.4s;
transition: 0.4s;
border-radius: 34px;
}

input:disabled {
cursor: not-allowed;
}

.slider:before {
position: absolute;
content: '';
height: 20px;
width: 20px;
left: 0px;
right: 0px;
bottom: -4px;
background-color: gray;
-webkit-transition: 0.4s;
transition: 0.4s;
border-radius: 50%;
}

input:checked + .slider:before {
-webkit-transform: translateX(18px);
-ms-transform: translateX(18px);
transform: translateX(18px);
background-color: #4250af;
}

input:checked + .slider-disabled {
background-color: gray;
}

input:checked + .slider-enabled {
background-color: #adcbfa;
}
</style>