feat: Ajout de spinners pendant l'initialisation des services
- Spinner global pendant l'initialisation des services (service.ts) - Spinner pour l'initialisation de la page d'accueil (home.ts) - Amélioration du feedback utilisateur pendant les phases d'attente - Design glassmorphism cohérent avec l'interface existante - Messages informatifs pour guider l'utilisateur - Gestion d'erreurs avec masquage automatique des spinners
This commit is contained in:
parent
60f19752d3
commit
3258b16a6e
@ -6,9 +6,99 @@ import { getCorrectDOM } from '../../utils/html.utils';
|
|||||||
import QrScannerComponent from '../../components/qrcode-scanner/qrcode-scanner-component';
|
import QrScannerComponent from '../../components/qrcode-scanner/qrcode-scanner-component';
|
||||||
import { navigate, registerAllListeners } from '../../router';
|
import { navigate, registerAllListeners } from '../../router';
|
||||||
|
|
||||||
|
// Home page loading spinner functions
|
||||||
|
function showHomeLoadingSpinner(message: string = 'Loading...') {
|
||||||
|
// Remove existing spinner if any
|
||||||
|
hideHomeLoadingSpinner();
|
||||||
|
|
||||||
|
// Create spinner overlay
|
||||||
|
const overlay = document.createElement('div');
|
||||||
|
overlay.id = 'home-loading-overlay';
|
||||||
|
overlay.style.cssText = `
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.7);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 9998;
|
||||||
|
backdrop-filter: blur(3px);
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Create spinner content
|
||||||
|
const spinnerContent = document.createElement('div');
|
||||||
|
spinnerContent.style.cssText = `
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 30px;
|
||||||
|
text-align: center;
|
||||||
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
max-width: 350px;
|
||||||
|
width: 90%;
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Create spinner
|
||||||
|
const spinner = document.createElement('div');
|
||||||
|
spinner.style.cssText = `
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border: 3px solid #f3f3f3;
|
||||||
|
border-top: 3px solid #3a506b;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
margin: 0 auto 15px auto;
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Create message
|
||||||
|
const messageEl = document.createElement('div');
|
||||||
|
messageEl.textContent = message;
|
||||||
|
messageEl.style.cssText = `
|
||||||
|
font-size: 14px;
|
||||||
|
color: #3a506b;
|
||||||
|
font-weight: 500;
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Add CSS animation if not already present
|
||||||
|
if (!document.getElementById('home-spinner-styles')) {
|
||||||
|
const style = document.createElement('style');
|
||||||
|
style.id = 'home-spinner-styles';
|
||||||
|
style.textContent = `
|
||||||
|
@keyframes spin {
|
||||||
|
0% { transform: rotate(0deg); }
|
||||||
|
100% { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
document.head.appendChild(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble spinner
|
||||||
|
spinnerContent.appendChild(spinner);
|
||||||
|
spinnerContent.appendChild(messageEl);
|
||||||
|
overlay.appendChild(spinnerContent);
|
||||||
|
|
||||||
|
// Add to document
|
||||||
|
document.body.appendChild(overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideHomeLoadingSpinner() {
|
||||||
|
const overlay = document.getElementById('home-loading-overlay');
|
||||||
|
if (overlay) {
|
||||||
|
overlay.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export { QrScannerComponent };
|
export { QrScannerComponent };
|
||||||
export async function initHomePage(): Promise<void> {
|
export async function initHomePage(): Promise<void> {
|
||||||
console.log('INIT-HOME');
|
console.log('INIT-HOME');
|
||||||
|
|
||||||
|
// Show loading spinner during home page initialization
|
||||||
|
showHomeLoadingSpinner('Initializing pairing interface...');
|
||||||
|
|
||||||
const container = getCorrectDOM('login-4nk-component') as HTMLElement;
|
const container = getCorrectDOM('login-4nk-component') as HTMLElement;
|
||||||
container.querySelectorAll('.tab').forEach((tab) => {
|
container.querySelectorAll('.tab').forEach((tab) => {
|
||||||
addSubscription(tab, 'click', () => {
|
addSubscription(tab, 'click', () => {
|
||||||
@ -20,12 +110,21 @@ export async function initHomePage(): Promise<void> {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
const service = await Services.getInstance();
|
const service = await Services.getInstance();
|
||||||
const spAddress = await service.getDeviceAddress();
|
const spAddress = await service.getDeviceAddress();
|
||||||
// generateQRCode(spAddress);
|
// generateQRCode(spAddress);
|
||||||
generateCreateBtn();
|
generateCreateBtn();
|
||||||
displayEmojis(spAddress);
|
displayEmojis(spAddress);
|
||||||
|
|
||||||
|
// Hide loading spinner after initialization
|
||||||
|
hideHomeLoadingSpinner();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error initializing home page:', error);
|
||||||
|
hideHomeLoadingSpinner();
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
// Add this line to populate the select when the page loads
|
// Add this line to populate the select when the page loads
|
||||||
await populateMemberSelect();
|
await populateMemberSelect();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,102 @@ const BOOTSTRAPURL = [import.meta.env.VITE_BOOTSTRAPURL || `${BASEURL}:8090`];
|
|||||||
const STORAGEURL = import.meta.env.VITE_STORAGEURL || `${BASEURL}:8081`;
|
const STORAGEURL = import.meta.env.VITE_STORAGEURL || `${BASEURL}:8081`;
|
||||||
const BLINDBITURL = import.meta.env.VITE_BLINDBITURL || `${BASEURL}:8000`;
|
const BLINDBITURL = import.meta.env.VITE_BLINDBITURL || `${BASEURL}:8000`;
|
||||||
const DEFAULTAMOUNT = 1000n;
|
const DEFAULTAMOUNT = 1000n;
|
||||||
|
|
||||||
|
// Global loading spinner functions
|
||||||
|
function showGlobalLoadingSpinner(message: string = 'Loading...') {
|
||||||
|
// Remove existing spinner if any
|
||||||
|
hideGlobalLoadingSpinner();
|
||||||
|
|
||||||
|
// Create spinner overlay
|
||||||
|
const overlay = document.createElement('div');
|
||||||
|
overlay.id = 'global-loading-overlay';
|
||||||
|
overlay.style.cssText = `
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.8);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 9999;
|
||||||
|
backdrop-filter: blur(5px);
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Create spinner content
|
||||||
|
const spinnerContent = document.createElement('div');
|
||||||
|
spinnerContent.style.cssText = `
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 40px;
|
||||||
|
text-align: center;
|
||||||
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
max-width: 400px;
|
||||||
|
width: 90%;
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Create spinner
|
||||||
|
const spinner = document.createElement('div');
|
||||||
|
spinner.style.cssText = `
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
border: 4px solid #f3f3f3;
|
||||||
|
border-top: 4px solid #3a506b;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
margin: 0 auto 20px auto;
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Create message
|
||||||
|
const messageEl = document.createElement('div');
|
||||||
|
messageEl.textContent = message;
|
||||||
|
messageEl.style.cssText = `
|
||||||
|
font-size: 16px;
|
||||||
|
color: #3a506b;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Create progress indicator
|
||||||
|
const progressEl = document.createElement('div');
|
||||||
|
progressEl.textContent = 'Please wait...';
|
||||||
|
progressEl.style.cssText = `
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Add CSS animation if not already present
|
||||||
|
if (!document.getElementById('global-spinner-styles')) {
|
||||||
|
const style = document.createElement('style');
|
||||||
|
style.id = 'global-spinner-styles';
|
||||||
|
style.textContent = `
|
||||||
|
@keyframes spin {
|
||||||
|
0% { transform: rotate(0deg); }
|
||||||
|
100% { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
document.head.appendChild(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble spinner
|
||||||
|
spinnerContent.appendChild(spinner);
|
||||||
|
spinnerContent.appendChild(messageEl);
|
||||||
|
spinnerContent.appendChild(progressEl);
|
||||||
|
overlay.appendChild(spinnerContent);
|
||||||
|
|
||||||
|
// Add to document
|
||||||
|
document.body.appendChild(overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideGlobalLoadingSpinner() {
|
||||||
|
const overlay = document.getElementById('global-loading-overlay');
|
||||||
|
if (overlay) {
|
||||||
|
overlay.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
const EMPTY32BYTES = String('').padStart(64, '0');
|
const EMPTY32BYTES = String('').padStart(64, '0');
|
||||||
|
|
||||||
export default class Services {
|
export default class Services {
|
||||||
@ -53,8 +149,16 @@ export default class Services {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log('initializing services');
|
console.log('initializing services');
|
||||||
|
|
||||||
|
// Show global loading spinner during initialization
|
||||||
|
showGlobalLoadingSpinner('Initializing services...');
|
||||||
|
|
||||||
Services.instance = await Services.initializing;
|
Services.instance = await Services.initializing;
|
||||||
Services.initializing = null; // Reset for potential future use
|
Services.initializing = null; // Reset for potential future use
|
||||||
|
|
||||||
|
// Hide loading spinner after initialization
|
||||||
|
hideGlobalLoadingSpinner();
|
||||||
|
|
||||||
return Services.instance;
|
return Services.instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -422,7 +422,14 @@ function showLoadingState() {
|
|||||||
const creatorFlow = container.querySelector('#creator-flow');
|
const creatorFlow = container.querySelector('#creator-flow');
|
||||||
const joinerFlow = container.querySelector('#joiner-flow');
|
const joinerFlow = container.querySelector('#joiner-flow');
|
||||||
|
|
||||||
if (loadingFlow) loadingFlow.style.display = 'block';
|
if (loadingFlow) {
|
||||||
|
loadingFlow.style.display = 'block';
|
||||||
|
// Update loading message
|
||||||
|
const loadingText = loadingFlow.querySelector('h2');
|
||||||
|
const loadingDesc = loadingFlow.querySelector('p');
|
||||||
|
if (loadingText) loadingText.textContent = 'Initializing...';
|
||||||
|
if (loadingDesc) loadingDesc.textContent = 'Setting up secure pairing interface';
|
||||||
|
}
|
||||||
if (creatorFlow) creatorFlow.style.display = 'none';
|
if (creatorFlow) creatorFlow.style.display = 'none';
|
||||||
if (joinerFlow) joinerFlow.style.display = 'none';
|
if (joinerFlow) joinerFlow.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user