Spaces:
Running
Running
| import { CONFIG } from "./config.js"; | |
| // Lazily load @huggingface/hub (resolved via the importmap in index.html). | |
| // Dynamic import means a CDN hiccup degrades liking only — never the whole app. | |
| let _hub = null; | |
| async function hub() { | |
| if (!_hub) _hub = await import("@huggingface/hub"); | |
| return _hub; | |
| } | |
| function load(key) { | |
| try { return JSON.parse(localStorage.getItem(key) || "null"); } catch { return null; } | |
| } | |
| function save(key, v) { | |
| try { localStorage.setItem(key, JSON.stringify(v)); } catch { /* ignore */ } | |
| } | |
| /** Returns the active OAuthResult or null (handles the redirect-back leg on load). */ | |
| export async function initOAuth() { | |
| let oauth = null; | |
| try { | |
| const { oauthHandleRedirectIfPresent } = await hub(); | |
| oauth = await oauthHandleRedirectIfPresent(); | |
| } catch { | |
| oauth = null; | |
| } | |
| oauth = oauth || load(CONFIG.oauthKey); | |
| if (oauth) { | |
| const exp = new Date(oauth.accessTokenExpiresAt).getTime(); | |
| if (Number.isFinite(exp) && exp < Date.now()) oauth = null; // expired | |
| } | |
| if (oauth) save(CONFIG.oauthKey, oauth); | |
| return oauth; | |
| } | |
| export async function signIn() { | |
| try { | |
| const { oauthLoginUrl } = await hub(); | |
| const opts = CONFIG.oauthScopes ? { scopes: CONFIG.oauthScopes } : {}; | |
| window.location.href = await oauthLoginUrl(opts); | |
| } catch { | |
| /* OAuth lib unavailable — stay signed out; likes go local */ | |
| } | |
| } | |
| export function signOut() { | |
| try { localStorage.removeItem(CONFIG.oauthKey); } catch { /* ignore */ } | |
| } | |
| /** | |
| * Attempts a real HF like/unlike. Returns "hf" on success, "local" on any failure/offline. | |
| * Caller persists the local fallback + UI. | |
| */ | |
| export async function likeOnHf(id, on, token) { | |
| if (!token) return "local"; | |
| try { | |
| const res = await fetch(`${CONFIG.apiBase}/api/spaces/${id}/like`, { | |
| method: on ? "POST" : "DELETE", | |
| headers: { Authorization: `Bearer ${token}` }, | |
| }); | |
| return res.ok ? "hf" : "local"; | |
| } catch { | |
| return "local"; | |
| } | |
| } | |