piclets / src /App.svelte
Fraser's picture
add UI options
62fead0
raw
history blame
5.45 kB
<script lang="ts">
import { onMount } from 'svelte';
import { authStore } from './lib/stores/auth';
import SignInButton from './lib/components/Auth/SignInButton.svelte';
import AuthBanner from './lib/components/Auth/AuthBanner.svelte';
import FluxGenerator from './lib/components/ImageGeneration/FluxGenerator.svelte';
import JoyCaption from './lib/components/ImageCaption/JoyCaption.svelte';
import RWKVGenerator from './lib/components/TextGeneration/RWKVGenerator.svelte';
import type { HuggingFaceLibs, GradioLibs, GradioClient, FluxGenerationResult } from './lib/types';
// These will be loaded from window after HF libs are loaded
let hfAuth: HuggingFaceLibs | null = $state(null);
let gradioClient: GradioLibs | null = $state(null);
// Gradio client instances
let fluxClient: GradioClient | null = $state(null);
let joyCaptionClient: GradioClient | null = $state(null);
let rwkvClient: GradioClient | null = $state(null);
// Current generated image for passing to caption component
let currentImageBlob: Blob | null = $state(null);
// Auth state from store
const auth = $derived(authStore);
onMount(async () => {
// Load HF libraries
const script1 = document.createElement('script');
script1.type = 'module';
script1.textContent = `
import {
oauthLoginUrl,
oauthHandleRedirectIfPresent
} from "https://cdn.jsdelivr.net/npm/@huggingface/[email protected]/+esm";
import { Client } from "https://cdn.jsdelivr.net/npm/@gradio/client/dist/index.min.js";
window.hfAuth = { oauthLoginUrl, oauthHandleRedirectIfPresent };
window.gradioClient = { Client };
`;
document.head.appendChild(script1);
// Wait for libraries to load
await new Promise(resolve => {
const checkLibs = setInterval(() => {
if (window.hfAuth && window.gradioClient) {
clearInterval(checkLibs);
resolve(undefined);
}
}, 100);
});
hfAuth = window.hfAuth as HuggingFaceLibs;
gradioClient = window.gradioClient as GradioLibs;
// Handle OAuth redirect
try {
const session = await hfAuth.oauthHandleRedirectIfPresent();
authStore.setSession(session);
// Start the app
await initializeClients(session?.accessToken || null);
} catch (err) {
console.error("OAuth handling error:", err);
authStore.setSession(null);
await initializeClients(null);
}
});
async function initializeClients(hfToken: string | null) {
if (!gradioClient) return;
authStore.setBannerMessage("Connecting to FLUX.1-schnell, Joy Caption, and RWKV…");
try {
const opts = hfToken ? { hf_token: hfToken } : {};
// Connect to all three spaces
fluxClient = await gradioClient.Client.connect(
"black-forest-labs/FLUX.1-schnell",
opts
);
joyCaptionClient = await gradioClient.Client.connect(
"fancyfeast/joy-caption-alpha-two",
opts
);
rwkvClient = await gradioClient.Client.connect(
"BlinkDL/RWKV-Gradio-2",
opts
);
authStore.setBannerMessage("");
} catch (err) {
console.error(err);
authStore.setBannerMessage(`❌ Failed to connect: ${err}`);
}
}
function handleImageGenerated(result: FluxGenerationResult, imageBlob: Blob) {
currentImageBlob = imageBlob;
}
</script>
<div class="app">
<div class="card">
<h1>FLUX-1 Schnell + Joy Caption + RWKV Space</h1>
<p>
This Svelte-powered Space demonstrates how to call remote Gradio Spaces while
letting <strong>each visitor's own Hugging Face subscription</strong> cover
the compute costs. Generate images with FLUX-1, caption them with Joy Caption, and generate text with RWKV.
</p>
{#if $auth.showSignIn}
<SignInButton {hfAuth} />
{/if}
<AuthBanner
message={$auth.bannerMessage}
visible={!!$auth.bannerMessage}
/>
{#if $auth.userInfo}
<p>Hello, {$auth.userInfo.name || $auth.userInfo.preferred_username}!</p>
{/if}
{#if fluxClient}
<FluxGenerator
client={fluxClient}
onImageGenerated={handleImageGenerated}
/>
{/if}
{#if joyCaptionClient}
<JoyCaption
client={joyCaptionClient}
currentImage={currentImageBlob}
/>
{/if}
{#if rwkvClient}
<RWKVGenerator client={rwkvClient} />
{/if}
<hr />
<p class="footer">
Source & docs:
<a href="https://huggingface.co/docs/hub/spaces-oauth" target="_blank">Spaces OAuth</a>,
<a href="https://github.com/huggingface/huggingface.js" target="_blank">huggingface.js</a>,
<a href="https://js.gradio.app" target="_blank">@gradio/client</a>
</p>
</div>
</div>
<style>
.app {
min-height: 100vh;
background: #f5f5f5;
padding: 2rem;
}
.card {
max-width: 900px;
margin: 0 auto;
background: #ffffff;
padding: 2rem;
border-radius: 10px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
h1 {
margin-top: 0;
}
hr {
margin: 3rem 0 2rem;
border: none;
border-top: 1px solid #eee;
}
.footer {
color: #666;
font-size: 0.9rem;
}
.footer a {
color: #007bff;
text-decoration: none;
}
.footer a:hover {
text-decoration: underline;
}
</style>