mindmime's picture
Upload folder using huggingface_hub
a03b3ba verified
raw
history blame contribute delete
No virus
3.85 kB
<script lang="ts">
import { createEventDispatcher, getContext, onMount, tick } from "svelte";
import { DropdownArrow } from "@gradio/icons";
import { click_outside } from "../utils/events";
import { layer_manager, type LayerScene } from "./utils";
import { EDITOR_KEY, type EditorContext } from "../ImageEditor.svelte";
import type { FileData } from "@gradio/client";
let show_layers = false;
export let layer_files: (FileData | null)[] | null = [];
const { pixi, current_layer, dimensions, register_context } =
getContext<EditorContext>(EDITOR_KEY);
const LayerManager = layer_manager();
let layers: LayerScene[] = [];
register_context("layers", {
init_fn: () => {
new_layer();
},
reset_fn: () => {
LayerManager.reset();
}
});
async function new_layer(): Promise<void> {
if (!$pixi) return;
const [active_layer, all_layers] = LayerManager.add_layer(
$pixi.layer_container,
$pixi.renderer,
...$dimensions
);
$current_layer = active_layer;
layers = all_layers;
}
$: render_layer_files(layer_files);
function is_not_null<T>(x: T | null): x is T {
return x !== null;
}
async function render_layer_files(
_layer_files: typeof layer_files
): Promise<void> {
await tick();
if (!_layer_files || _layer_files.length == 0) return;
if (!$pixi) return;
const fetch_promises = await Promise.all(
_layer_files.map((f) => {
if (!f || !f.url) return null;
return fetch(f.url);
})
);
const blobs = await Promise.all(
fetch_promises.map((p) => {
if (!p) return null;
return p.blob();
})
);
LayerManager.reset();
let last_layer: [LayerScene, LayerScene[]] | null = null;
for (const blob of blobs.filter(is_not_null)) {
last_layer = await LayerManager.add_layer_from_blob(
$pixi.layer_container,
$pixi.renderer,
blob
);
}
if (!last_layer) return;
$current_layer = last_layer[0];
layers = last_layer[1];
}
onMount(async () => {
await tick();
if (!$pixi) return;
$pixi = { ...$pixi!, get_layers: LayerManager.get_layers };
});
</script>
<div
class="layer-wrap"
class:closed={!show_layers}
use:click_outside={() => (show_layers = false)}
>
<button aria-label="Show Layers" on:click={() => (show_layers = !show_layers)}
>Layers<span class="layer-toggle"><DropdownArrow /></span></button
>
{#if show_layers}
<ul>
{#each layers as layer, i (i)}
<li>
<button
class:selected_layer={$current_layer === layer}
on:click={() =>
($current_layer = LayerManager.change_active_layer(i))}
>Layer {i + 1}</button
>
</li>
{/each}
<li>
<button aria-label="Add Layer" on:click={new_layer}> +</button>
</li>
</ul>
{/if}
</div>
<style>
.layer-toggle {
width: 20px;
transform: rotate(0deg);
}
.closed .layer-toggle {
transform: rotate(-90deg);
}
.layer-wrap {
position: absolute;
bottom: 0;
left: 0;
display: inline-block;
border: 1px solid var(--block-border-color);
border-radius: var(--radius-md);
transition: var(--button-transition);
box-shadow: var(--button-shadow);
text-align: left;
border-bottom: none;
border-left: none;
border-bottom-right-radius: 0;
border-top-left-radius: 0;
background-color: var(--background-fill-primary);
overflow: hidden;
}
.layer-wrap button {
display: inline-flex;
justify-content: flex-start;
align-items: flex-start;
padding: var(--size-2) var(--size-4);
width: 100%;
border-bottom: 1px solid var(--block-border-color);
}
.layer-wrap li:last-child button {
border-bottom: none;
text-align: center;
}
.closed > button {
border-bottom: none;
}
.layer-wrap button:hover {
background-color: var(--background-fill-secondary);
}
.selected_layer {
background-color: var(--color-accent) !important;
color: white;
font-weight: bold;
}
</style>