mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-03-20 15:41:40 -04:00
238 lines
12 KiB
HTML
238 lines
12 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<!--
|
|
==========================================================================================================
|
|
|
|
db 88 88 8b d8 88
|
|
d88b 88 "" `8b d8' 88 ,d
|
|
d8'`8b 88 `8b d8' 88 88
|
|
d8' `8b 88 88 ,adPPYYba, ,adPPYba, `8b d8' ,adPPYYba, 88 88 88 MM88MMM
|
|
d8YaaaaY8b 88 88 "" `Y8 I8[ "" `8b d8' "" `Y8 88 88 88 88
|
|
d8""""""""8b 88 88 ,adPPPPP88 `"Y8ba, `8b d8' ,adPPPPP88 88 88 88 88
|
|
d8' `8b 88 88 88, ,88 aa ]8I `888' 88, ,88 "8a, ,a88 88 88,
|
|
d8' `8b 88 88 `"8bbdP"Y8 `"YbbdP"' `8' `"8bbdP"Y8 `"YbbdP'Y8 88 "Y888
|
|
|
|
==========================================================================================================
|
|
|
|
AliasVault - Free open-source password and (email) alias manager.
|
|
Build (UTC): @BuildVersion
|
|
|
|
Source code: https://github.com/lanedirt/AliasVault
|
|
License: MIT
|
|
-->
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"/>
|
|
<title>AliasVault</title>
|
|
<base href="/" />
|
|
<link rel="stylesheet" href="css/app.css?v=@CacheBuster" />
|
|
<link rel="icon" type="image/png" href="favicon.png" />
|
|
<link href="css/tailwind.css?v=@CacheBuster" rel="stylesheet">
|
|
<link href="AliasVault.Client.styles.css?v=@CacheBuster" rel="stylesheet" />
|
|
<link rel="manifest" href="manifest.json" />
|
|
<link rel="apple-touch-icon" sizes="500x500" href="img/icon-500.png" />
|
|
<link rel="apple-touch-icon" sizes="192x192" href="img/icon-192.png" />
|
|
</head>
|
|
|
|
<body class="bg-gray-100 dark:bg-gray-900" av-disable="true">
|
|
<div id="loading-screen">
|
|
<div class="fixed inset-0 flex items-center justify-center px-6 pt-8 pb-8">
|
|
<div class="w-full max-w-md space-y-4">
|
|
<div class="p-6 sm:p-8 bg-white rounded-lg shadow dark:bg-gray-800">
|
|
<div class="text-center">
|
|
<div class="inner">
|
|
<div class="index-aliasvault-inline-spinner mx-auto">
|
|
<div class="index-cloud-shape-inline">
|
|
<div class="index-dot-inline index-delay-1"></div>
|
|
<div class="index-dot-inline index-delay-2"></div>
|
|
<div class="index-dot-inline index-delay-3"></div>
|
|
<div class="index-dot-inline index-delay-4"></div>
|
|
</div>
|
|
</div>
|
|
<h2 class="mt-4 text-xl font-semibold text-gray-900 dark:text-white">AliasVault is loading</h2>
|
|
<p class="mt-2 text-sm text-gray-500 dark:text-gray-400">
|
|
Initializing secure environment. AliasVault prioritizes your privacy by running entirely in your browser. The first load might take a short while.
|
|
</p>
|
|
<div class="loading-progress-text text-sm font-medium text-gray-700 dark:text-gray-300 mt-4"></div>
|
|
<div class="mt-4 text-center">
|
|
<p id="security-quote" class="text-sm text-primary-600 italic"></p>
|
|
</div>
|
|
<div id="error-message" class="hidden text-red-600 dark:text-red-400 mt-4"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.index-aliasvault-inline-spinner {
|
|
height: 51px;
|
|
width: 112px;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
.index-cloud-shape-inline {
|
|
border: 6px solid #eabf69;
|
|
border-radius: 9999px;
|
|
padding: 13px 26px;
|
|
display: flex;
|
|
gap: 10px;
|
|
align-items: center;
|
|
background-color: transparent;
|
|
box-shadow: 0 0 4px 2px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.index-dot-inline {
|
|
width: 10px;
|
|
height: 10px;
|
|
border-radius: 9999px;
|
|
background-color: #eabf69;
|
|
animation: index-pulse-inverted 1.4s infinite ease-in-out;
|
|
}
|
|
|
|
.index-delay-1 { animation-delay: 0s; }
|
|
.index-delay-2 { animation-delay: 0.2s; }
|
|
.index-delay-3 { animation-delay: 0.4s; }
|
|
.index-delay-4 { animation-delay: 0.6s; }
|
|
|
|
@keyframes index-pulse-inverted {
|
|
0%, 100% { opacity: 0.3; transform: scale(1); }
|
|
50% { opacity: 1; transform: scale(1.3); }
|
|
}
|
|
</style>
|
|
</div>
|
|
|
|
<div id="refresh-button" class="text-center w-full mt-4 p-6 sm:p-8 bg-white rounded-lg shadow dark:bg-gray-800 hidden">
|
|
<p class="text-sm text-gray-600 dark:text-gray-400 mb-2">If loading seems stuck, you can click the button below to refresh the page.</p>
|
|
<a href="javascript:window.location.reload(true)" class="inline-block px-4 py-2 bg-primary-600 text-white text-sm font-medium rounded-md hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 transition duration-150 ease-in-out">
|
|
Refresh Page
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="app">
|
|
</div>
|
|
|
|
<div id="blazor-error-ui" class="text-white bg-red-700 dark:bg-red-900 p-6 border-t-2 border-red-500 dark:border-red-800">
|
|
<div class="container mx-auto max-w-screen-xl px-4">
|
|
<div class="flex flex-col sm:flex-row items-center justify-between gap-4">
|
|
<div class="flex items-center">
|
|
<svg class="w-8 h-8 text-white mr-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
|
|
</svg>
|
|
<span>An unhandled error has occurred. Please try reloading the page. If the issue persists, please contact support.</span>
|
|
</div>
|
|
<div class="flex items-center gap-4">
|
|
<a href="" class="reload flex items-center px-4 py-2 bg-red-600 hover:bg-red-700 rounded-md transition-colors duration-150">
|
|
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/>
|
|
</svg>
|
|
Reload Page
|
|
</a>
|
|
<a class="dismiss hover:text-red-200">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
|
|
</svg>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
const securityQuotes = [
|
|
"Your identity is your most valuable asset. Protect it like one.",
|
|
"In the digital world, a strong password is your first line of defense.",
|
|
"Security is not a product, but a process.",
|
|
"The weakest link in the security chain is the human element.",
|
|
"Security is always excessive until it's not enough.",
|
|
"Trust, but verify - especially online.",
|
|
"Your data is only as secure as your weakest password.",
|
|
"The most secure password is the one you can't remember.",
|
|
];
|
|
|
|
const quoteElement = document.getElementById('security-quote');
|
|
const randomIndex = Math.floor(Math.random() * securityQuotes.length);
|
|
quoteElement.textContent = `"${securityQuotes[randomIndex]}"`;
|
|
|
|
function manageLoadingScreen() {
|
|
const startTime = new Date().getTime();
|
|
const minDisplayTime = 1000;
|
|
const checkInterval = 500;
|
|
const refreshButtonTimeout = 300000;
|
|
|
|
const appElement = document.getElementById('app');
|
|
const refreshButton = document.getElementById('refresh-button');
|
|
|
|
appElement.style.visibility = 'hidden';
|
|
loadingScreen.style.display = 'flex';
|
|
|
|
// Show refresh button after 30 seconds
|
|
setTimeout(() => {
|
|
refreshButton.classList.remove('hidden');
|
|
}, refreshButtonTimeout);
|
|
|
|
// Add click event listener to refresh button
|
|
refreshButton.addEventListener('click', () => {
|
|
window.location.reload();
|
|
});
|
|
|
|
const checkContentAndTime = () => {
|
|
const elapsedTime = new Date().getTime() - startTime;
|
|
const hasContent = appElement.innerHTML.trim() !== '';
|
|
|
|
if (elapsedTime >= minDisplayTime && hasContent) {
|
|
loadingScreen.style.display = 'none';
|
|
appElement.style.removeProperty('visibility');
|
|
clearInterval(intervalId);
|
|
} else if (elapsedTime % 1000 < checkInterval) {
|
|
if (!('WebAssembly' in window)) {
|
|
showError("AliasVault requires WebAssembly, which this browser does not support. Try using a more modern browser that supports WebAssembly.");
|
|
clearInterval(intervalId);
|
|
}
|
|
}
|
|
};
|
|
|
|
const intervalId = setInterval(checkContentAndTime, checkInterval);
|
|
}
|
|
|
|
const loadingScreen = document.getElementById('loading-screen');
|
|
const errorMessageElement = document.getElementById('error-message');
|
|
|
|
const showError = (message) => {
|
|
errorMessageElement.textContent = message;
|
|
errorMessageElement.classList.remove('hidden');
|
|
document.querySelector('.loading-progress-text').classList.add('hidden');
|
|
document.querySelector('svg.animate-spin').classList.add('hidden');
|
|
};
|
|
|
|
// Listen for unhandled errors
|
|
window.addEventListener('error', function(event) {
|
|
if (event.error && event.error.message && event.error.message.includes('WebAssembly')) {
|
|
showError("AliasVault requires WebAssembly, which this browser does not support. Try using a more modern browser that supports WebAssembly.");
|
|
}
|
|
});
|
|
|
|
// Listen for unhandled promise rejections
|
|
window.addEventListener('unhandledrejection', function(event) {
|
|
if (event.reason && event.reason.message && event.reason.message.includes('WebAssembly')) {
|
|
showError("AliasVault requires WebAssembly, which this browser does not support. Try using a more modern browser that supports WebAssembly.");
|
|
}
|
|
});
|
|
|
|
window.addEventListener('load', manageLoadingScreen);
|
|
</script>
|
|
<script src="js/crypto.js?v=@CacheBuster" async></script>
|
|
<script src="js/utilities.js?v=@CacheBuster" async></script>
|
|
<script src="_framework/blazor.webassembly.js?v=@CacheBuster" async></script>
|
|
<script src="lib/qrcode.min.js?v=@CacheBuster" defer></script>
|
|
<script>
|
|
if ('serviceWorker' in navigator) {
|
|
navigator.serviceWorker.register('service-worker.js');
|
|
}
|
|
</script>
|
|
</body>
|
|
|
|
</html>
|