diff --git a/src/pages/home/home.ts b/src/pages/home/home.ts index eeedce5..4ef3d49 100755 --- a/src/pages/home/home.ts +++ b/src/pages/home/home.ts @@ -6,9 +6,99 @@ import { getCorrectDOM } from '../../utils/html.utils'; import QrScannerComponent from '../../components/qrcode-scanner/qrcode-scanner-component'; 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 async function initHomePage(): Promise { console.log('INIT-HOME'); + + // Show loading spinner during home page initialization + showHomeLoadingSpinner('Initializing pairing interface...'); + const container = getCorrectDOM('login-4nk-component') as HTMLElement; container.querySelectorAll('.tab').forEach((tab) => { addSubscription(tab, 'click', () => { @@ -20,11 +110,20 @@ export async function initHomePage(): Promise { }); }); - const service = await Services.getInstance(); - const spAddress = await service.getDeviceAddress(); - // generateQRCode(spAddress); - generateCreateBtn(); - displayEmojis(spAddress); + try { + const service = await Services.getInstance(); + const spAddress = await service.getDeviceAddress(); + // generateQRCode(spAddress); + generateCreateBtn(); + 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 await populateMemberSelect(); diff --git a/src/services/service.ts b/src/services/service.ts index fa2d7fa..bf30a6e 100755 --- a/src/services/service.ts +++ b/src/services/service.ts @@ -15,6 +15,102 @@ const BOOTSTRAPURL = [import.meta.env.VITE_BOOTSTRAPURL || `${BASEURL}:8090`]; const STORAGEURL = import.meta.env.VITE_STORAGEURL || `${BASEURL}:8081`; const BLINDBITURL = import.meta.env.VITE_BLINDBITURL || `${BASEURL}:8000`; 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'); export default class Services { @@ -53,8 +149,16 @@ export default class Services { } console.log('initializing services'); + + // Show global loading spinner during initialization + showGlobalLoadingSpinner('Initializing services...'); + Services.instance = await Services.initializing; Services.initializing = null; // Reset for potential future use + + // Hide loading spinner after initialization + hideGlobalLoadingSpinner(); + return Services.instance; } diff --git a/src/utils/sp-address.utils.ts b/src/utils/sp-address.utils.ts index cfad21f..9eddd33 100755 --- a/src/utils/sp-address.utils.ts +++ b/src/utils/sp-address.utils.ts @@ -421,8 +421,15 @@ function showLoadingState() { const loadingFlow = container.querySelector('#loading-flow'); const creatorFlow = container.querySelector('#creator-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 (joinerFlow) joinerFlow.style.display = 'none'; }