mirror of
https://github.com/ivabus/gui
synced 2025-04-23 14:07:14 +03:00
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:
parent
8d0378656a
commit
b880f336d3
4 changed files with 139 additions and 62 deletions
127
modules/desktop/src/components/package-card/bg-image.svelte
Normal file
127
modules/desktop/src/components/package-card/bg-image.svelte
Normal 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>
|
|
@ -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%);
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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) => {
|
||||
|
|
Loading…
Reference in a new issue