| |
| |
| |
| |
|
|
| import { oauthLoginUrl, oauthHandleRedirectIfPresent, uploadFile, createRepo } from "https://cdn.jsdelivr.net/npm/@huggingface/hub@0.15.2/+esm"; |
|
|
| const HF_API = 'https://huggingface.co/api'; |
| const NEW_SPACE_NAME = 'reachy_mini_remote_control'; |
|
|
| |
| let currentUser = null; |
| let userToken = null; |
| let oauthResult = null; |
|
|
| |
| |
| |
| async function initAuth() { |
| try { |
| |
| oauthResult = await oauthHandleRedirectIfPresent(); |
|
|
| if (oauthResult) { |
| |
| currentUser = oauthResult.userInfo.preferred_username; |
| userToken = oauthResult.accessToken; |
|
|
| |
| sessionStorage.setItem('hf_token', userToken); |
| sessionStorage.setItem('hf_username', currentUser); |
| sessionStorage.setItem('hf_token_expires', oauthResult.accessTokenExpiresAt); |
|
|
| console.log('OAuth authentication successful:', currentUser); |
| showAuthenticatedView(); |
| await checkForExistingSpace(); |
| } else { |
| |
| const storedToken = sessionStorage.getItem('hf_token'); |
| const storedUser = sessionStorage.getItem('hf_username'); |
| const tokenExpires = sessionStorage.getItem('hf_token_expires'); |
|
|
| if (storedToken && storedUser && tokenExpires && new Date(tokenExpires) > new Date()) { |
| |
| userToken = storedToken; |
| currentUser = storedUser; |
| showAuthenticatedView(); |
| await checkForExistingSpace(); |
| } |
| } |
| } catch (error) { |
| console.error('OAuth initialization error:', error); |
| |
| showLoginView(); |
| } |
| } |
|
|
| |
| |
| |
| async function loginToHuggingFace() { |
| try { |
| |
| const loginUrl = await oauthLoginUrl(); |
| window.location.href = loginUrl; |
| } catch (error) { |
| console.error('OAuth login error:', error); |
| alert('Failed to initiate login. Please try again.'); |
| } |
| } |
|
|
| |
| |
| |
| function showLoginView() { |
| document.getElementById('login-view').style.display = 'block'; |
| document.getElementById('authenticated-view').style.display = 'none'; |
| } |
|
|
| |
| |
| |
| function showAuthenticatedView() { |
| document.getElementById('login-view').style.display = 'none'; |
| document.getElementById('authenticated-view').style.display = 'block'; |
| document.getElementById('username').textContent = currentUser; |
| } |
|
|
| |
| |
| |
| async function checkForExistingSpace() { |
| try { |
| const response = await fetch(`${HF_API}/spaces/${currentUser}/${NEW_SPACE_NAME}`, { |
| headers: { |
| 'Authorization': `Bearer ${userToken}` |
| } |
| }); |
|
|
| if (response.ok) { |
| showExistingSpaceView(); |
| } else { |
| showNoSpaceView(); |
| } |
| } catch (error) { |
| console.error('Error checking for space:', error); |
| showNoSpaceView(); |
| } |
| } |
|
|
| |
| |
| |
| function showNoSpaceView() { |
| document.getElementById('no-space-view').style.display = 'block'; |
| document.getElementById('has-space-view').style.display = 'none'; |
| } |
|
|
| |
| |
| |
| function showExistingSpaceView() { |
| document.getElementById('no-space-view').style.display = 'none'; |
| document.getElementById('has-space-view').style.display = 'block'; |
|
|
| |
| const spaceUrl = `${currentUser}/${NEW_SPACE_NAME}`; |
| const wsUri = `wss://${currentUser.replace('_', '')}-${NEW_SPACE_NAME}.hf.space`; |
|
|
| document.getElementById('space-url-display').textContent = spaceUrl; |
| document.getElementById('private-uri').textContent = wsUri; |
| document.getElementById('space-link').href = `https://huggingface.co/spaces/${spaceUrl}`; |
| } |
|
|
| |
| |
| |
| async function cloneSpace() { |
| const btn = document.querySelector('#no-space-view .btn'); |
| const btnText = document.getElementById('clone-btn-text'); |
| const originalText = btnText.textContent; |
|
|
| try { |
| |
| btn.disabled = true; |
| btnText.textContent = '⏳ Creating space...'; |
|
|
| |
| await createRepo({ |
| repo: `${currentUser}/${NEW_SPACE_NAME}`, |
| accessToken: userToken, |
| credentials: { |
| accessToken: userToken |
| }, |
| hubUrl: 'https://huggingface.co', |
| spaceHardware: 'cpu-basic', |
| spaceSdk: 'gradio' |
| }); |
|
|
| btnText.textContent = '⏳ Uploading files...'; |
|
|
| |
| const files = ['README.md', 'app.py', 'requirements.txt', 'packages.txt']; |
|
|
| for (const fileName of files) { |
| |
| const fileResponse = await fetch(`remote_control_space/${fileName}`); |
| if (!fileResponse.ok) { |
| console.error(`Failed to fetch ${fileName}`); |
| continue; |
| } |
| const content = await fileResponse.blob(); |
|
|
| |
| await uploadFile({ |
| repo: `${currentUser}/${NEW_SPACE_NAME}`, |
| accessToken: userToken, |
| credentials: { |
| accessToken: userToken |
| }, |
| file: { |
| path: fileName, |
| content: content |
| } |
| }); |
| } |
|
|
| btnText.textContent = '✓ Space created successfully!'; |
|
|
| |
| setTimeout(() => { |
| showExistingSpaceView(); |
| }, 1500); |
|
|
| } catch (error) { |
| console.error('Error creating space:', error); |
| alert(`Failed to create space: ${error.message}\n\nPlease try again or create the space manually.`); |
| btn.disabled = false; |
| btnText.textContent = originalText; |
| } |
| } |
|
|
| |
| |
| |
| function logout() { |
| if (confirm('Are you sure you want to sign out?')) { |
| localStorage.removeItem('hf_token'); |
| localStorage.removeItem('hf_username'); |
| currentUser = null; |
| userToken = null; |
|
|
| |
| document.getElementById('login-view').style.display = 'block'; |
| document.getElementById('authenticated-view').style.display = 'none'; |
| } |
| } |
|
|
| |
| |
| |
| function copyToClipboard(text, buttonElement) { |
| navigator.clipboard.writeText(text).then(() => { |
| |
| if (buttonElement) { |
| const originalText = buttonElement.textContent; |
| buttonElement.textContent = '✓ Copied!'; |
| setTimeout(() => { |
| buttonElement.textContent = originalText; |
| }, 2000); |
| } |
| }).catch(err => { |
| console.error('Failed to copy:', err); |
| alert('Failed to copy to clipboard'); |
| }); |
| } |
|
|
| |
| |
| |
| function copyPrivateUri(event) { |
| const uri = document.getElementById('private-uri').textContent; |
| copyToClipboard(uri, event.currentTarget); |
| } |
|
|
| |
| window.loginToHuggingFace = loginToHuggingFace; |
| window.cloneSpace = cloneSpace; |
| window.logout = logout; |
| window.copyToClipboard = copyToClipboard; |
| window.copyPrivateUri = copyPrivateUri; |
|
|
| |
| document.addEventListener('DOMContentLoaded', initAuth); |
|
|