Transition between loading states in the album Ui

master
Araozu 2024-05-31 14:04:28 -05:00
parent 2b03c39dfe
commit a224d5baf8
4 changed files with 67 additions and 29 deletions

View File

@ -1,49 +1,90 @@
import { For, Show, createEffect, createMemo, createResource, createSignal, onCleanup, onMount } from "solid-js"; import { batch, createEffect, createMemo, createResource, createSignal, onMount } from "solid-js";
import { GetAlbumCover, GetRandomAlbums, LoadRandomAlbums } from "../../wailsjs/go/main/App"; import { GetAlbumCover, GetRandomAlbums, TriggerAlbumReload } from "../../wailsjs/go/main/App";
import { main } from "../../wailsjs/go/models"; import { main } from "../../wailsjs/go/models";
import { createStore } from "solid-js/store";
type AlbumsData = {
status: "loading" | "ok",
albums: Array<main.Album | null>
}
export function Home() { export function Home() {
const [hidden, setHidden] = createSignal(true); const [hidden, setHidden] = createSignal(true);
const [albums, {mutate, refetch}] = createResource<Array<main.Album | null>>(GetRandomAlbums);
const [albumsStore, setAlbumsStore] = createStore<AlbumsData>({
status: "loading",
albums: new Array(20).fill(null),
});
onMount(() => { onMount(() => {
// Fade in the UI // Fade in the UI
setTimeout(() => setHidden(false), 150); setTimeout(() => setHidden(false), 150);
// Load the albums
loadAlbums();
}); });
const reload = () => { // Loads the random albums from Go.
LoadRandomAlbums(); // This function, when called multiple times, returns the same set.
mutate((new Array(20)).map(() => null)); const loadAlbums = async() => {
setTimeout(refetch, 100); const response = await GetRandomAlbums();
// Update the albums
batch(() => {
for (let i = 0; i < response.length; i += 1) {
const album = response[i];
setAlbumsStore("albums", i, album);
}
});
}; };
const triggerAlbumReload = () => {
// Assign all albums to null
batch(() => {
for (let i = 0; i < 20; i += 1) {
setAlbumsStore("albums", i, null);
}
});
TriggerAlbumReload();
setTimeout(loadAlbums, 50);
};
const els = albumsStore.albums.map((_, idx) => (<Album albums={albumsStore.albums} idx={idx} />));
return ( return (
<div class={`min-h-screen ${hidden() ? "opacity-0" : "opacity-100"} transition-opacity`}> <div class={`min-h-screen ${hidden() ? "opacity-0" : "opacity-100"} transition-opacity`}>
<h1 class="font-black text-2xl pt-6 pb-4 pl-2"> <h1 class="font-black text-2xl pt-6 pb-4 pl-2">
Random albums Random albums
<button <button
class="text-xs font-normal mx-1 p-1 rounded underline hover:bg-zinc-900" class="text-xs font-normal mx-1 p-1 rounded underline hover:bg-zinc-900"
onClick={reload} onClick={triggerAlbumReload}
> >
Reload Reload
</button> </button>
</h1> </h1>
<div class="pb-4 overflow-scroll whitespace-nowrap"> <div class="pb-4 overflow-scroll whitespace-nowrap">
<For each={albums()}> {els}
{(album) => <Album album={album} />}
</For>
</div> </div>
</div> </div>
); );
} }
function Album(props: { album: main.Album | null }) { function Album(props: { albums: Array<main.Album | null>, idx: number }) {
const [coverBytes, {mutate, refetch}] = createResource<Array<number> | null>(async() => GetAlbumCover(props.album?.id ?? "")); const [coverBytes, {mutate, refetch}] = createResource<Array<number> | null>(async() => GetAlbumCover(props.albums[props.idx]?.id ?? ""));
const [albumName, setAlbumName] = createSignal("");
const [artistName, setArtistName] = createSignal("");
const album = createMemo(() => props.albums[props.idx]);
createEffect(() => { createEffect(() => {
if (!props.album) { const a = album();
if (a === null) {
mutate(null); mutate(null);
return; return;
} else {
setAlbumName(a.name);
setArtistName(a.albumArtist);
} }
refetch(); refetch();
@ -57,27 +98,24 @@ function Album(props: { album: main.Album | null }) {
return `data:;base64,${bytes}`; return `data:;base64,${bytes}`;
}); });
const isNull = createMemo(() => !props.album); const isNull = createMemo(() => !album());
const opacity = createMemo(() => `${isNull() ? "opacity-0" : "opacity-100"} transition-opacity`); const opacity = createMemo(() => `${isNull() ? "opacity-0" : "opacity-100"} transition-opacity`);
return ( return (
<div class="inline-block mx-2 p-1 w-32 rounded bg-zinc-900"> <div class="inline-block mx-2 p-1 w-32 rounded bg-zinc-900">
<Show when={isNull()}> <div class="w-30 h-30" >
<div class="w-30 h-30" />
</Show>
<Show when={!isNull()}>
<img <img
class={`inline-block rounded w-30 h-30 transition-opacity ${coverBytes.state === "ready" ? "opacity-100" : "opacity-0"}`} class={`inline-block rounded w-30 h-30 transition-opacity ${coverBytes.state === "ready" ? "opacity-100" : "opacity-0"}`}
src={base64Image()} src={base64Image()}
alt="" alt=""
/> />
</Show> </div>
<div class={`text-sm overflow-hidden overflow-ellipsis pt-1 ${opacity()}`}> <div class={`text-sm overflow-hidden overflow-ellipsis pt-1 ${opacity()}`}>
{props.album?.name ?? "..."} {albumName()}
</div> </div>
<div class={`text-xs overflow-hidden overflow-ellipsis ${opacity()}`}> <div class={`text-xs overflow-hidden overflow-ellipsis ${opacity()}`}>
{props.album?.albumArtist ?? "..."} {artistName()}
</div> </div>
</div> </div>

View File

@ -8,6 +8,6 @@ export function GetRandomAlbums():Promise<Array<main.Album>>;
export function Greet(arg1:string):Promise<string>; export function Greet(arg1:string):Promise<string>;
export function LoadRandomAlbums():Promise<void>;
export function Login(arg1:string,arg2:string,arg3:string):Promise<boolean>; export function Login(arg1:string,arg2:string,arg3:string):Promise<boolean>;
export function TriggerAlbumReload():Promise<void>;

View File

@ -14,10 +14,10 @@ export function Greet(arg1) {
return window['go']['main']['App']['Greet'](arg1); return window['go']['main']['App']['Greet'](arg1);
} }
export function LoadRandomAlbums() {
return window['go']['main']['App']['LoadRandomAlbums']();
}
export function Login(arg1, arg2, arg3) { export function Login(arg1, arg2, arg3) {
return window['go']['main']['App']['Login'](arg1, arg2, arg3); return window['go']['main']['App']['Login'](arg1, arg2, arg3);
} }
export function TriggerAlbumReload() {
return window['go']['main']['App']['TriggerAlbumReload']();
}

View File

@ -69,7 +69,7 @@ func (a *App) Login(server, username, password string) (bool, error) {
} }
// Triggers a reload of random albums // Triggers a reload of random albums
func (a *App) LoadRandomAlbums() { func (a *App) TriggerAlbumReload() {
go loadAlbums(serverUrl) go loadAlbums(serverUrl)
} }