move bg image to its own component + preloader (#491)

* move bg image to its own component

* recache image if non-existent, add transition to show image

---------

Co-authored-by: neil molina <neil@neils-MacBook-Pro.local>
This commit is contained in:
Neil 2023-04-24 12:17:15 +08:00 committed by GitHub
parent 8d0378656a
commit b880f336d3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 139 additions and 62 deletions

View file

@ -0,0 +1,127 @@
<script lang="ts">
import type { GUIPackage } from "$libs/types";
import { onMount } from "svelte";
import { packagesStore } from "$libs/stores";
let clazz = '';
export { clazz as class };
export let layout: "bottom" | "right" | "left" = "bottom";
export let pkg: GUIPackage;
const defaultImgUrl = "/images/default-thumb.jpg";
let loadedImg = "";
let loaded = false;
const loadImage = async (url:string): Promise<string> => {
const image = new Image();
image.src = url;
return new Promise((resolve, reject) => {
image.onload = () => {
loadedImg = url;
setTimeout(() => {
loaded = true;
}, 300);
resolve(url);
};
image.onerror = () => {
reject(new Error(`file/url does not exist ${url}`));
};
});
};
const recachePkg = async () => {
const url = await packagesStore.cachePkgImage(pkg)
loadImage(url);
}
onMount(() => {
if (pkg.cached_image_url) {
loadImage(pkg.cached_image_url)
.catch(() => {
if (pkg.thumb_image_url) {
loadImage(pkg.thumb_image_url);
recachePkg();
}
});
} else if (pkg.thumb_image_url) {
recachePkg();
}
});
</script>
<section class="bg-center {clazz} {layout}"
class:grayscale={!loaded}
style="background-image: url({defaultImgUrl})">
<div class="transition-all opacity-0" class:opacity-100={loaded} style="background-image: url({loadedImg})">
<!-- dup image: save processing power instead of computing the blur across all the HTML layers -->
<aside class="blur-sm {layout} ransition-all opacity-0" class:opacity-100={loaded}>
<figure class="bg-center" style="background-image: url({loadedImg})" />
</aside>
</section>
<style>
section {
width: 100%;
height: 100%;
background-size: cover;
box-sizing: border-box;
background-repeat: no-repeat;
}
div {
position: absolute;
left: 0px;
bottom: 0px;
width: 100%;
height: 100%;
background-size: cover;
box-sizing: border-box;
background-repeat: no-repeat;
}
aside {
position: absolute;
bottom: 0px;
width: 100%;
overflow: hidden;
}
aside.bottom {
left: 0px;
height: 50%;
}
aside.left {
left: 0px;
height: 100%;
width: 40%;
}
aside.right {
height: 100%;
right: 0px;
width: 60%;
}
figure {
position: absolute;
bottom: 0px;
width: 100%;
height: 338px;
background-size: cover;
background-repeat: no-repeat;
}
aside.bottom figure {
left: 0px;
}
aside.right figure {
height: 100%;
width: 150%;
right: 0px;
}
aside.left figure {
height: 100%;
width: 250%;
left: 0px;
}
</style>

View file

@ -3,10 +3,9 @@
import ProgressCircle from "@tea/ui/progress-circle/progress-circle.svelte";
import { PackageStates, type GUIPackage } from "$libs/types";
import { findRecentInstalledVersion } from "$libs/packages/pkg-utils";
import BgImage from "./bg-image.svelte";
import PackageInstallButton from "$components/package-install-button/package-install-button.svelte";
import PackageInstalledBadge from "$components/package-install-button/package-installed-badge.svelte";
import { onMount } from "svelte";
import { packagesStore } from "$libs/stores";
export let pkg: GUIPackage;
export let link: string;
@ -14,9 +13,6 @@
export let layout: "bottom" | "right" | "left" = "bottom";
$: imgUrl = pkg?.cached_image_url || (!pkg.thumb_image_url.includes("https://tea.xyz")
? "/images/default-thumb.jpg"
: pkg.thumb_image_url);
export let onClickCTA = async () => {
console.log("do nothing");
};
@ -32,19 +28,14 @@
const preventPropagation = (evt: MouseEvent) => evt.stopPropagation();
onMount(() => {
if (pkg && !pkg?.cached_image_url) packagesStore.cachePkgImage(pkg);
});
</script>
<section
class="package-card border-gray relative h-auto border bg-center {layout}"
class="package-card border-gray relative h-auto border {layout}"
class:active={isActive}
style="background-image: url({imgUrl})"
>
<aside class="blur-sm {layout}">
<figure class="bg-center" style="background-image: url({imgUrl})" />
</aside>
<BgImage class="absolute w-full h-full top-0 left-0" {layout} {pkg}/>
<a href={link} on:mousedown={activate} on:mouseup={deactivate} on:mouseleave={deactivate}>
<div class="package-card-content absolute h-full w-full flex-col justify-between">
<div class="hint-container">
@ -131,51 +122,6 @@
box-shadow: 0px 0px 0px 2px rgba(128, 0, 255, 0.5);
}
aside {
position: absolute;
bottom: 0px;
width: 100%;
height: 50%;
overflow: hidden;
}
aside.bottom {
left: 0px;
}
aside.left {
left: 0px;
height: 100%;
width: 40%;
}
aside.right {
height: 100%;
right: 0px;
width: 60%;
}
figure {
position: absolute;
bottom: 0px;
width: 100%;
height: 340px;
background-size: cover;
background-repeat: no-repeat;
}
aside.bottom {
left: 0px;
}
aside.right figure {
height: 100%;
width: 150%;
right: 0px;
}
aside.left figure {
height: 100%;
width: 250%;
left: 0px;
}
.content-container {
height: 50%;
background: linear-gradient(180deg, rgba(26, 26, 26, 0.3) 0%, rgba(26, 26, 26, 0.75) 72.92%);

View file

@ -87,7 +87,7 @@
{#each packages as pkg, index}
{#if index < limit}
<div class="card z-1 p-1" class:animate-puls={pkg.state === PackageStates.INSTALLING}>
<Package tab={packageFilter} {pkg} layout="vertical"/>
<Package tab={packageFilter} {pkg} layout="bottom"/>
</div>
{/if}
{/each}

View file

@ -254,13 +254,17 @@ To read more about this package go to [${guiPkg.homepage}](${guiPkg.homepage}).
writePackageCacheWithDebounce(pkgs);
});
const cachePkgImage = async (pkg: GUIPackage) => {
const cachePkgImage = async (pkg: GUIPackage): Promise<string> => {
let cacheFileURL = "";
updatePackage(pkg.full_name, { cached_image_url: "" });
if (pkg.thumb_image_url && !pkg.thumb_image_url.includes("package-thumb-nolabel4.jpg")) {
const cacheFileURL = await cacheImageURL(pkg.thumb_image_url);
if (cacheFileURL) {
const result = await cacheImageURL(pkg.thumb_image_url);
if (result) {
cacheFileURL = result;
updatePackage(pkg.full_name, { cached_image_url: cacheFileURL });
}
}
return cacheFileURL;
};
listenToChannel("install-progress", (data: any) => {