feat: create standalone pairing page like other setup pages
**Motivations :** - Créer une page standalone pour le pairing comme les autres étapes (security-setup, wallet-setup, etc.) - Uniformiser le format des pages de setup avec une structure HTML complète - Faciliter la redirection depuis block-sync vers pairing **Modifications :** - Créer src/pages/pairing/pairing.html (page HTML complète comme les autres) - Créer src/pages/pairing/pairing.ts (charge la logique depuis home.ts) - Ajouter la route pairing dans router.ts - Mettre à jour les redirections dans block-sync.ts pour utiliser pairing.html - Mettre à jour checkStorageStateAndNavigate pour rediriger vers pairing **Pages affectées :** - src/pages/pairing/pairing.html (nouveau fichier) - src/pages/pairing/pairing.ts (nouveau fichier) - src/router.ts (ajout route pairing) - src/pages/block-sync/block-sync.ts (redirection vers pairing.html)
This commit is contained in:
parent
5a1826034e
commit
47e3166851
@ -32,8 +32,8 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||||||
if (continueBtn) {
|
if (continueBtn) {
|
||||||
continueBtn.addEventListener('click', async () => {
|
continueBtn.addEventListener('click', async () => {
|
||||||
console.log('🔗 Redirecting to pairing page...');
|
console.log('🔗 Redirecting to pairing page...');
|
||||||
// Rediriger vers la racine pour que le router charge la page home correctement
|
// Rediriger vers la page de pairing standalone
|
||||||
window.location.href = '/';
|
window.location.href = '/src/pages/pairing/pairing.html';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,7 +186,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||||||
continueBtn.disabled = false;
|
continueBtn.disabled = false;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
console.log('🔗 Auto-redirecting to pairing page...');
|
console.log('🔗 Auto-redirecting to pairing page...');
|
||||||
window.location.href = '/';
|
window.location.href = '/src/pages/pairing/pairing.html';
|
||||||
}, 3000);
|
}, 3000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -226,7 +226,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||||||
updateStatus('✅ Redirection automatique vers le pairing dans 3 secondes...', 'success');
|
updateStatus('✅ Redirection automatique vers le pairing dans 3 secondes...', 'success');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
console.log('🔗 Auto-redirecting to pairing page...');
|
console.log('🔗 Auto-redirecting to pairing page...');
|
||||||
window.location.href = '/';
|
window.location.href = '/src/pages/pairing/pairing.html';
|
||||||
}, 3000);
|
}, 3000);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Failed to verify wallet update - last_scan not found');
|
throw new Error('Failed to verify wallet update - last_scan not found');
|
||||||
|
|||||||
85
src/pages/pairing/pairing.html
Normal file
85
src/pages/pairing/pairing.html
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Pairing - LeCoffre</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
background: white;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 40px;
|
||||||
|
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
|
||||||
|
max-width: 600px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
text-align: center;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
text-align: center;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status.loading {
|
||||||
|
background: #e3f2fd;
|
||||||
|
color: #1976d2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status.success {
|
||||||
|
background: #e8f5e8;
|
||||||
|
color: #2e7d32;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status.error {
|
||||||
|
background: #ffebee;
|
||||||
|
color: #c62828;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pairing-content {
|
||||||
|
min-height: 200px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<link rel="stylesheet" href="../../4nk.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>🔐 Pairing</h1>
|
||||||
|
<p class="subtitle">Appairage sécurisé des appareils</p>
|
||||||
|
|
||||||
|
<div class="status loading" id="status">
|
||||||
|
🔄 Initialisation en cours...
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="pairing-content">
|
||||||
|
<!-- Le contenu de pairing sera injecté ici -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="module" src="./pairing.ts"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
142
src/pages/pairing/pairing.ts
Normal file
142
src/pages/pairing/pairing.ts
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
import { DeviceReaderService } from '../../services/device-reader.service';
|
||||||
|
import { SecureCredentialsService } from '../../services/secure-credentials.service';
|
||||||
|
import { SecurityModeService } from '../../services/security-mode.service';
|
||||||
|
import { addSubscription } from '../../utils/subscription.utils';
|
||||||
|
import { displayEmojis, generateCreateBtn, addressToEmoji, prepareAndSendPairingTx } from '../../utils/sp-address.utils';
|
||||||
|
import { getCorrectDOM } from '../../utils/html.utils';
|
||||||
|
import { IframePairingComponent } from '../../components/iframe-pairing/iframe-pairing';
|
||||||
|
import { checkPBKDF2Key, checkWalletWithRetries } from '../../utils/prerequisites.utils';
|
||||||
|
import loginHtml from '../home/home.html?raw';
|
||||||
|
import loginCss from '../../4nk.css?raw';
|
||||||
|
|
||||||
|
// Extend WindowEventMap to include custom events
|
||||||
|
declare global {
|
||||||
|
interface WindowEventMap {
|
||||||
|
'pairing-words-generated': CustomEvent;
|
||||||
|
'pairing-status-update': CustomEvent;
|
||||||
|
'pairing-success': CustomEvent;
|
||||||
|
'pairing-error': CustomEvent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let isInitializing = false;
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', async () => {
|
||||||
|
if (isInitializing) {
|
||||||
|
console.log('⚠️ Pairing page already initializing, skipping...');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isInitializing = true;
|
||||||
|
console.log('🔐 Pairing page loaded');
|
||||||
|
|
||||||
|
const status = document.getElementById('status') as HTMLElement;
|
||||||
|
const pairingContent = document.getElementById('pairing-content') as HTMLElement;
|
||||||
|
|
||||||
|
function updateStatus(message: string, type: 'loading' | 'success' | 'error') {
|
||||||
|
if (status) {
|
||||||
|
status.textContent = message;
|
||||||
|
status.className = `status ${type}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vérifier les prérequis en base de données
|
||||||
|
console.log('🔍 Verifying prerequisites...');
|
||||||
|
updateStatus('🔍 Vérification des prérequis...', 'loading');
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log('🔧 Getting device reader service...');
|
||||||
|
const deviceReader = DeviceReaderService.getInstance();
|
||||||
|
|
||||||
|
// Vérifier que le PBKDF2 key existe d'abord
|
||||||
|
const pbkdf2KeyResult = await checkPBKDF2Key();
|
||||||
|
if (!pbkdf2KeyResult) {
|
||||||
|
console.log('⚠️ PBKDF2 key not found, redirecting to security-setup...');
|
||||||
|
updateStatus('⚠️ Redirection vers la configuration de sécurité...', 'loading');
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = '/src/pages/security-setup/security-setup.html';
|
||||||
|
}, 1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vérifier que le wallet existe en base
|
||||||
|
const wallet = await checkWalletWithRetries();
|
||||||
|
if (!wallet) {
|
||||||
|
console.log('⚠️ Wallet still not found after retries, redirecting to wallet-setup...');
|
||||||
|
updateStatus('⚠️ Redirection vers la configuration du wallet...', 'loading');
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = '/src/pages/wallet-setup/wallet-setup.html';
|
||||||
|
}, 1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vérifier que le wallet contient bien les données attendues
|
||||||
|
if (wallet.sp_wallet?.birthday !== undefined) {
|
||||||
|
console.log('✅ Wallet found in database with birthday:', wallet.sp_wallet.birthday);
|
||||||
|
} else {
|
||||||
|
throw new Error('Wallet found but missing required data (sp_wallet or birthday)');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vérifier que le birthday est configuré (> 0)
|
||||||
|
if (!wallet.sp_wallet.birthday || wallet.sp_wallet.birthday === 0) {
|
||||||
|
console.log('⚠️ Birthday not configured, redirecting to birthday-setup...');
|
||||||
|
updateStatus('⚠️ Redirection vers la configuration de la date anniversaire...', 'loading');
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = '/src/pages/birthday-setup/birthday-setup.html';
|
||||||
|
}, 1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('✅ All prerequisites verified for pairing page');
|
||||||
|
|
||||||
|
// Charger le contenu de pairing depuis home.html
|
||||||
|
updateStatus('🔄 Initialisation du pairing...', 'loading');
|
||||||
|
|
||||||
|
if (pairingContent) {
|
||||||
|
pairingContent.innerHTML = `
|
||||||
|
<style>
|
||||||
|
${loginCss}
|
||||||
|
</style>
|
||||||
|
${loginHtml}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Importer et initialiser la logique de pairing depuis home.ts
|
||||||
|
const { initHomePage } = await import('../home/home');
|
||||||
|
await initHomePage();
|
||||||
|
|
||||||
|
updateStatus('✅ Prêt pour le pairing', 'success');
|
||||||
|
setTimeout(() => {
|
||||||
|
if (status) {
|
||||||
|
status.style.display = 'none';
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
|
console.log('✅ Pairing page initialization completed');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Error initializing pairing page:', error);
|
||||||
|
updateStatus(`❌ Erreur: ${(error as Error).message}`, 'error');
|
||||||
|
|
||||||
|
// Si l'erreur est liée aux prérequis, rediriger vers la page appropriée
|
||||||
|
const errorMessage = (error as Error).message;
|
||||||
|
if (errorMessage.includes('PBKDF2') || errorMessage.includes('security')) {
|
||||||
|
console.log('⚠️ Security error detected, redirecting to security-setup...');
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = '/src/pages/security-setup/security-setup.html';
|
||||||
|
}, 2000);
|
||||||
|
} else if (errorMessage.includes('wallet') || errorMessage.includes('device')) {
|
||||||
|
console.log('⚠️ Wallet error detected, redirecting to wallet-setup...');
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = '/src/pages/wallet-setup/wallet-setup.html';
|
||||||
|
}, 2000);
|
||||||
|
} else if (errorMessage.includes('birthday')) {
|
||||||
|
console.log('⚠️ Birthday error detected, redirecting to birthday-setup...');
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = '/src/pages/birthday-setup/birthday-setup.html';
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
isInitializing = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
@ -20,6 +20,7 @@ const routes: { [key: string]: string } = {
|
|||||||
'wallet-setup': '/src/pages/wallet-setup/wallet-setup.html',
|
'wallet-setup': '/src/pages/wallet-setup/wallet-setup.html',
|
||||||
'birthday-setup': '/src/pages/birthday-setup/birthday-setup.html',
|
'birthday-setup': '/src/pages/birthday-setup/birthday-setup.html',
|
||||||
'block-sync': '/src/pages/block-sync/block-sync.html',
|
'block-sync': '/src/pages/block-sync/block-sync.html',
|
||||||
|
'pairing': '/src/pages/pairing/pairing.html',
|
||||||
};
|
};
|
||||||
|
|
||||||
export let currentRoute = '';
|
export let currentRoute = '';
|
||||||
@ -63,9 +64,8 @@ export async function checkStorageStateAndNavigate(): Promise<void> {
|
|||||||
// Vérifier si la date anniversaire est configurée (wallet avec birthday > 0)
|
// Vérifier si la date anniversaire est configurée (wallet avec birthday > 0)
|
||||||
if (device.sp_wallet.birthday && device.sp_wallet.birthday > 0) {
|
if (device.sp_wallet.birthday && device.sp_wallet.birthday > 0) {
|
||||||
console.log('🎂 Birthday is configured, navigating to pairing');
|
console.log('🎂 Birthday is configured, navigating to pairing');
|
||||||
// Ne pas vérifier le pairing ici pour éviter d'initialiser WebAssembly
|
// Rediriger vers la page de pairing standalone
|
||||||
// La page home.ts vérifiera le pairing si nécessaire
|
await navigate('pairing');
|
||||||
await navigate('home');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ async function handleLocation(path: string) {
|
|||||||
console.log('📍 Route HTML:', routeHtml);
|
console.log('📍 Route HTML:', routeHtml);
|
||||||
|
|
||||||
// Pour les pages de setup, rediriger directement vers la page HTML
|
// Pour les pages de setup, rediriger directement vers la page HTML
|
||||||
if (path === 'security-setup' || path === 'wallet-setup' || path === 'birthday-setup' || path === 'block-sync') {
|
if (path === 'security-setup' || path === 'wallet-setup' || path === 'birthday-setup' || path === 'block-sync' || path === 'pairing') {
|
||||||
console.log('📍 Processing setup route:', path);
|
console.log('📍 Processing setup route:', path);
|
||||||
window.location.href = routeHtml;
|
window.location.href = routeHtml;
|
||||||
return;
|
return;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user