import React, { useState, useEffect } from 'react';
import {
Dialog,
DialogTitle,
DialogContent,
DialogActions,
Button,
Typography,
TextField,
Box,
CircularProgress,
Stepper,
Step,
StepLabel,
Link,
Alert,
LinearProgress
} from '@mui/material';
import api from '../api';
import { hfAuthDialogStyles } from '../theme';
const HfAuthDialog = ({ open, onClose, onModelsDownloaded }) => {
const [activeStep, setActiveStep] = useState(0);
const [missingModels, setMissingModels] = useState([]);
const [checkingStatus, setCheckingStatus] = useState(true);
const [token, setToken] = useState('');
const [error, setError] = useState(null);
const [isProcessing, setIsProcessing] = useState(false);
const [downloadingModel, setDownloadingModel] = useState(null);
const steps = ['Check required models', 'Authenticate', 'Download models'];
useEffect(() => {
if (open) {
checkModelStatus();
} else {
setActiveStep(0);
setError(null);
setToken('');
setMissingModels([]);
}
}, [open]);
const checkModelStatus = async () => {
setCheckingStatus(true);
setError(null);
try {
const response = await api.get('/api/base-models/status');
const models = response.data.base_models;
const missing = Object.entries(models)
.filter(([_, info]) => !info.downloaded)
.map(([id, info]) => ({ id, ...info }));
setMissingModels(missing);
if (missing.length === 0) {
setActiveStep(3);
} else {
setActiveStep(1);
}
} catch (err) {
setError(err.response?.data?.error || err.message || 'Failed to check model status.');
} finally {
setCheckingStatus(false);
}
};
const handleLogin = async () => {
if (!token.trim()) {
setError('Please enter a Hugging Face token.');
return;
}
setIsProcessing(true);
setError(null);
try {
await api.post('/api/hf-login', { token: token.trim() });
setActiveStep(2);
startDownloads();
} catch (err) {
setError(err.response?.data?.error || err.message || 'Authentication failed. Please check your token.');
setIsProcessing(false);
}
};
const startDownloads = async () => {
try {
for (const model of missingModels) {
setDownloadingModel(model.name);
await api.post(`/api/models/${model.id}/accept-terms`);
await api.post(`/api/models/${model.id}/download`);
}
setActiveStep(3);
if (onModelsDownloaded) {
onModelsDownloaded();
}
} catch (err) {
setError(err.response?.data?.error || err.message || 'Failed to download models.');
} finally {
setIsProcessing(false);
setDownloadingModel(null);
}
};
const handleClose = () => {
if (isProcessing && activeStep === 2) {
return;
}
onClose(activeStep === 3);
};
const getStepContent = (stepIndex) => {
if (checkingStatus) {
return (
Checking model availability...
);
}
switch (stepIndex) {
case 1:
return (
Some required base models are missing. You need a Hugging Face access token to download them.
Before proceeding, please ensure you have visited huggingface.co and accepted the terms of use for the required models (e.g., stabilityai/stable-audio-open-1.0).
setToken(e.target.value)}
placeholder="hf_xxxxxxxxxxxxxxxxxxx..."
margin="normal"
variant="outlined"
/>
You can get a token from{' '}
your Hugging Face settings
. "Read" access to public gated repos is needed.
);
case 2:
return (
Downloading {downloadingModel}...
This may take several minutes depending on your connection speed. Do not close the application.
);
case 3:
return (
All models are ready!
You can now close this dialog and begin using Fragmenta.
);
default:
return "Unknown step";
}
};
return (
);
};
export default HfAuthDialog;