Skip to content

Commit

Permalink
Merge pull request #141 from 3rob3/dev.jw.web-auto-reload
Browse files Browse the repository at this point in the history
Auto-Reload on Web
  • Loading branch information
3rob3 authored Sep 20, 2024
2 parents 5d92ce9 + 617f04f commit cd46a71
Show file tree
Hide file tree
Showing 8 changed files with 233 additions and 15 deletions.
1 change: 1 addition & 0 deletions docker/docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ services:
- 5173:5173
volumes:
- ~/immichFrame_Config:/app/Config
- ../immichFrame.Web/src:/app/src
# - PATH/TO/CONFIG:/app/Config
13 changes: 12 additions & 1 deletion immichFrame.Web/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import ts from 'typescript-eslint';
import svelte from 'eslint-plugin-svelte';
import prettier from 'eslint-config-prettier';
import globals from 'globals';
import parser from 'svelte-eslint-parser';

/** @type {import('eslint').Linter.Config[]} */
export default [
Expand All @@ -22,12 +23,22 @@ export default [
{
files: ['**/*.svelte'],
languageOptions: {
parser: parser,
ecmaVersion: 5,
sourceType: 'script',

parserOptions: {
parser: ts.parser
parser: '@typescript-eslint/parser'
}
}
},
{
ignores: ['build/', '.svelte-kit/', 'dist/']
},
{
files: ['*.ts'],
rules: {
'no-undef': 'off'
}
}
];
5 changes: 1 addition & 4 deletions immichFrame.Web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --check . && eslint .",
"format": "prettier --write .",
"api": "oazapfts https://localhost:7018/swagger/v1/swagger.json src/lib/immichFrameApi.ts",
"dev-up": "docker compose -f ../docker/docker-compose.dev.yml up --remove-orphans || make dev-down",
"dev-down": "docker compose -f ../docker/docker-compose.dev.yml down --remove-orphans",
"dev-update": "docker compose -f ../docker/docker-compose.dev.yml up --build -V --remove-orphans"
"api": "oazapfts https://localhost:7018/swagger/v1/swagger.json src/lib/immichFrameApi.ts"
},
"devDependencies": {
"@sveltejs/adapter-auto": "^3.0.0",
Expand Down
14 changes: 7 additions & 7 deletions immichFrame.Web/src/lib/components/elements/imageOverlay.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
function clickNext() {
dispatch('next');
dispatch('back');
dispatch('settings');
}
function clickBack() {
dispatch('back');
Expand All @@ -23,23 +21,23 @@

<div id="image-overlay" class="grid grid-cols-3 gap-2 content-stretch">
<div class="overlay-item group">
<button on:click={clickBack} class="opacity-0 group-hover:opacity-100"
<button on:click={clickBack} class="opacity-0 group-hover:opacity-100 frame-color"
><Icon title="Text" path={mdiChevronLeft} size="20em" /></button
>
</div>

<div class="overlay-item grid grid-rows-3 gap-2 content-stretch">
<button on:click={clickSettings} class="opacity-0 hover:opacity-100"
<button on:click={clickSettings} class="opacity-0 hover:opacity-100 frame-color"
><Icon title="Text" path={mdiCog} size="20em" /></button
>
<button on:click={clickPause} class="opacity-0 hover:opacity-100"
<button on:click={clickPause} class="opacity-0 hover:opacity-100 frame-color"
><Icon title="Text" path={mdiPause} size="20em" /></button
>
<div></div>
</div>

<div class="overlay-item group">
<button on:click={clickNext} class="opacity-0 group-hover:opacity-100"
<button on:click={clickNext} class="opacity-0 group-hover:opacity-100 frame-color"
><Icon title="Text" path={mdiChevronRight} size="20em" />
</button>
</div>
Expand All @@ -62,8 +60,10 @@
justify-content: center; /* Centers the SVG horizontally */
align-items: center; /* Optionally, centers the SVG vertically as well */
/* background-color: rgba(75, 75, 75, 0.4); */
color: wheat;
height: 100%;
width: 100%;
}
.frame-color {
color: wheat;
}
</style>
101 changes: 101 additions & 0 deletions immichFrame.Web/src/lib/components/elements/progress-bar.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<script context="module" lang="ts">
export enum ProgressBarStatus {
Playing = 'playing',
Paused = 'paused'
}
</script>

<script lang="ts">
import { handlePromiseError } from '$lib/utils';
import { createEventDispatcher, onMount } from 'svelte';
import { tweened } from 'svelte/motion';
/**
* Autoplay on mount
* @default false
*/
export let autoplay = false;
/**
* Progress bar status
*/
export let status: ProgressBarStatus = ProgressBarStatus.Paused;
export let hidden = false;
export let duration = 5;
const onChange = async () => {
progress = setDuration(duration);
await play();
};
let progress = setDuration(duration);
// svelte 5, again....
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
$: duration, handlePromiseError(onChange());
$: {
if ($progress === 1) {
dispatch('done');
}
}
const dispatch = createEventDispatcher<{
done: void;
playing: void;
paused: void;
}>();
onMount(async () => {
if (autoplay) {
await play();
}
});
export const play = async () => {
status = ProgressBarStatus.Playing;
dispatch('playing');
await progress.set(1);
};
export const pause = async () => {
status = ProgressBarStatus.Paused;
dispatch('paused');
await progress.set($progress);
};
export const restart = async (autoplay: boolean) => {
await progress.set(0);
if (autoplay) {
await play();
}
};
export const reset = async () => {
status = ProgressBarStatus.Paused;
await progress.set(0);
};
function setDuration(newDuration: number) {
return tweened<number>(0, {
duration: (from: number, to: number) => (to ? newDuration * 1000 * (to - from) : 0)
});
}
</script>

{#if !hidden}
<span
class="absolute left-0 bottom-0 h-[3px] framebg-color"
style:width={`${$progress * 100}%`}
/>
{/if}

<style>
.framebg-color {
background-color: wheat;
}
</style>
62 changes: 59 additions & 3 deletions immichFrame.Web/src/lib/components/home-page/home-page.svelte
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
<script lang="ts">
import * as api from '$lib/immichFrameApi';
import Image from '../elements/image.svelte';
import { onMount } from 'svelte';
import ThumbHashImage from '../elements/thumbHashImage.svelte';
import ImageOverlay from '../elements/imageOverlay.svelte';
import Clock from '../elements/clock.svelte';
import ProgressBar, { ProgressBarStatus } from '$lib/components/elements/progress-bar.svelte';
import { slideshowStore } from '$lib/stores/slideshow.store';
import { onDestroy, onMount } from 'svelte';
api.defaults.baseUrl = 'http://localhost:8080/'; // TODO: replace configurable settings
let imageData: Blob | null;
let assetData: api.AssetResponseDto | null;
const { restartProgress, stopProgress } = slideshowStore;
let progressBarStatus: ProgressBarStatus;
let progressBar: ProgressBar;
let unsubscribeRestart: () => void;
let unsubscribeStop: () => void;
async function loadImage() {
let assetRequest = await api.getAsset();
Expand All @@ -28,15 +38,61 @@
imageData = imageRequest.data;
}
onMount(async () => loadImage());
onMount(async () => {
unsubscribeRestart = restartProgress.subscribe((value) => {
if (value) {
progressBar.restart(value);
}
});
unsubscribeStop = stopProgress.subscribe((value) => {
if (value) {
progressBar.restart(false);
}
});
await loadImage();
});
onDestroy(() => {
if (unsubscribeRestart) {
unsubscribeRestart();
}
if (unsubscribeStop) {
unsubscribeStop();
}
});
const handleDone = async () => {
await loadImage();
progressBar.restart(true);
};
</script>

<section id="home-page" class="fixed grid h-screen w-screen bg-black">
{#if imageData && assetData}
<Clock />
<ImageOverlay on:next={async () => loadImage()} />
<ImageOverlay
on:next={async () => {
await loadImage();
progressBar.restart(true);
}}
on:back={async () => {
await loadImage();
progressBar.restart(true);
}}
/>
<ThumbHashImage thumbHash={assetData.thumbhash ?? ''} />
<Image data={imageData} />
<ProgressBar
autoplay
hidden={false}
duration={5}
bind:this={progressBar}
bind:status={progressBarStatus}
on:done={handleDone}
/>
{:else}
<!-- maybe show immich logo?-->
<p class="text-white">LOADING ...</p>
Expand Down
48 changes: 48 additions & 0 deletions immichFrame.Web/src/lib/stores/slideshow.store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { writable } from 'svelte/store';

export enum SlideshowState {
PlaySlideshow = 'play-slideshow',
StopSlideshow = 'stop-slideshow',
None = 'none',
}


function createSlideshowStore() {
const restartState = writable<boolean>(false);
const stopState = writable<boolean>(false);

const slideshowState = writable<SlideshowState>(SlideshowState.None);

return {
restartProgress: {
subscribe: restartState.subscribe,
set: (value: boolean) => {

console.log('restartProgress value is: ')
console.log(value)
// Trigger an action whenever the restartProgress is set to true. Automatically
// reset the restart state after that
if (value) {
restartState.set(true);
restartState.set(false);
}
},
},
stopProgress: {
subscribe: stopState.subscribe,
set: (value: boolean) => {
console.log('stopProgress value is: ')
console.log(value)
// Trigger an action whenever the stopProgress is set to true. Automatically
// reset the stop state after that
if (value) {
stopState.set(true);
stopState.set(false);
}
},
},
slideshowState
};
}

export const slideshowStore = createSlideshowStore();
4 changes: 4 additions & 0 deletions immichFrame.Web/src/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
export const decodeBase64 = (data: string) => Uint8Array.from(atob(data), (c) => c.charCodeAt(0));

export const handlePromiseError = <T>(promise: Promise<T>): void => {
promise.catch((error) => console.error(`[utils.ts]:handlePromiseError ${error}`, error));
};

0 comments on commit cd46a71

Please sign in to comment.