feat(index.html): implement dark mode toggle and enhance theme handling

This commit is contained in:
pacnpal
2025-01-29 13:25:10 -05:00
parent 4ed14db4f7
commit 0d482fa33e

View File

@@ -1,10 +1,24 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en" class="dark:bg-gray-900">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SimpleGuardHome</title> <title>SimpleGuardHome</title>
<script src="https://unpkg.com/@tailwindcss/browser@4" integrity="sha384-fsXZ0Oru5QjGkveFx8DdmBAyKdwnJ7TnbRzDN5LROCKt8PAN8h7y7oqCwtk9cN68" crossorigin="anonymous"></script> <!-- Load Tailwind first -->
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
darkMode: 'class'
}
// Initialize theme before page load
const storedTheme = localStorage.getItem('color-theme');
if (storedTheme === 'dark') {
document.documentElement.classList.add('dark');
} else if (storedTheme === 'light') {
document.documentElement.classList.remove('dark');
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/2.3.4/purify.min.js" integrity="sha384-KGmzmwrs7oAU2sG5qfETslFsscVcCaxQrX2d7PW7I9bTrsuTD/eSMFr9jaMS9i+b" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/2.3.4/purify.min.js" integrity="sha384-KGmzmwrs7oAU2sG5qfETslFsscVcCaxQrX2d7PW7I9bTrsuTD/eSMFr9jaMS9i+b" crossorigin="anonymous"></script>
<script> <script>
function escapeHtml(unsafe) { function escapeHtml(unsafe) {
@@ -23,11 +37,11 @@
const isBlocked = data.reason.startsWith('Filtered'); const isBlocked = data.reason.startsWith('Filtered');
if (isBlocked) { if (isBlocked) {
resultDiv.innerHTML = ` resultDiv.innerHTML = `
<div class="bg-red-100 border-l-4 border-red-500 text-red-700 p-4 mb-4"> <div class="bg-red-100 dark:bg-red-900/30 border-l-4 border-red-500 text-red-700 dark:text-red-300 p-4 mb-4">
<p class="font-bold">Domain is blocked</p> <p class="font-bold">Domain is blocked</p>
<p class="text-sm"><strong>${escapeHtml(domain)}</strong> is blocked</p> <p class="text-sm"><strong>${escapeHtml(domain)}</strong> is blocked</p>
<p class="text-sm">Reason: ${escapeHtml(data.reason)}</p> <p class="text-sm">Reason: ${escapeHtml(data.reason)}</p>
${data.rules?.length ? `<p class="text-sm font-mono bg-red-50 p-2 mt-1 rounded">Rule: ${escapeHtml(data.rules[0].text)}</p>` : ''} ${data.rules?.length ? `<p class="text-sm font-mono bg-red-50 dark:bg-red-900/50 p-2 mt-1 rounded">Rule: ${escapeHtml(data.rules[0].text)}</p>` : ''}
${data.service_name ? `<p class="text-sm mt-2">Service: ${escapeHtml(data.service_name)}</p>` : ''} ${data.service_name ? `<p class="text-sm mt-2">Service: ${escapeHtml(data.service_name)}</p>` : ''}
</div>`; </div>`;
unblockDiv.innerHTML = ` unblockDiv.innerHTML = `
@@ -37,7 +51,7 @@
</button>`; </button>`;
} else { } else {
resultDiv.innerHTML = ` resultDiv.innerHTML = `
<div class="bg-green-100 border-l-4 border-green-500 text-green-700 p-4"> <div class="bg-green-100 dark:bg-green-900/30 border-l-4 border-green-500 text-green-700 dark:text-green-300 p-4">
<p class="font-bold">Domain is not blocked</p> <p class="font-bold">Domain is not blocked</p>
<p class="text-sm"><strong>${escapeHtml(domain)}</strong> is allowed</p> <p class="text-sm"><strong>${escapeHtml(domain)}</strong> is allowed</p>
<p class="text-xs mt-2">Status: ${escapeHtml(data.reason)}</p> <p class="text-xs mt-2">Status: ${escapeHtml(data.reason)}</p>
@@ -70,7 +84,7 @@
domain = preprocessDomain(rawInput); domain = preprocessDomain(rawInput);
} catch (error) { } catch (error) {
resultDiv.innerHTML = ` resultDiv.innerHTML = `
<div class="bg-yellow-100 border-l-4 border-yellow-500 text-yellow-700 p-4"> <div class="bg-yellow-100 dark:bg-yellow-900/30 border-l-4 border-yellow-500 text-yellow-700 dark:text-yellow-300 p-4">
<p class="font-bold">Invalid Input</p> <p class="font-bold">Invalid Input</p>
<p class="text-sm">${escapeHtml(error.message)}</p> <p class="text-sm">${escapeHtml(error.message)}</p>
</div>`; </div>`;
@@ -174,18 +188,26 @@
} }
</script> </script>
</head> </head>
<body class="bg-gray-100 min-h-screen"> <body class="bg-gray-100 dark:bg-gray-900 min-h-screen transition-colors duration-200">
<button id="theme-toggle" class="fixed top-4 right-4 p-2 rounded-lg bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors duration-200">
<svg id="theme-toggle-dark-icon" class="hidden w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"></path>
</svg>
<svg id="theme-toggle-light-icon" class="hidden w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"></path>
</svg>
</button>
<div class="container mx-auto px-4 py-8 max-w-2xl"> <div class="container mx-auto px-4 py-8 max-w-2xl">
<h1 class="text-3xl font-bold text-center mb-8 text-gray-800">SimpleGuardHome</h1> <h1 class="text-3xl font-bold text-center mb-8 text-gray-800 dark:text-white">SimpleGuardHome</h1>
<div class="bg-white rounded-lg shadow-md p-6"> <div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6">
<form onsubmit="checkDomain(event)" class="mb-6"> <form onsubmit="checkDomain(event)" class="mb-6">
<div class="mb-4"> <div class="mb-4">
<label for="domain" class="block text-gray-700 text-sm font-bold mb-2"> <label for="domain" class="block text-gray-700 dark:text-gray-300 text-sm font-bold mb-2">
Enter Domain to Check Enter Domain to Check
</label> </label>
<input type="text" id="domain" name="domain" required <input type="text" id="domain" name="domain" required
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 dark:text-gray-200 dark:bg-gray-700 dark:border-gray-600 leading-tight focus:outline-none focus:shadow-outline"
placeholder="example.com" placeholder="example.com"
title="Please enter a valid domain name"> title="Please enter a valid domain name">
</div> </div>
@@ -199,7 +221,60 @@
<div id="unblock-action" class="mt-4 text-center"></div> <div id="unblock-action" class="mt-4 text-center"></div>
</div> </div>
<div class="mt-4 text-center text-gray-600 text-sm"> <script>
document.addEventListener('DOMContentLoaded', function() {
// Theme toggle functionality
const themeToggleDarkIcon = document.getElementById('theme-toggle-dark-icon');
const themeToggleLightIcon = document.getElementById('theme-toggle-light-icon');
// Change the icons inside the button based on previous settings
function setThemeIcons() {
if (document.documentElement.classList.contains('dark')) {
themeToggleDarkIcon.classList.add('hidden');
themeToggleLightIcon.classList.remove('hidden');
} else {
themeToggleLightIcon.classList.add('hidden');
themeToggleDarkIcon.classList.remove('hidden');
}
}
// Check for theme preference
const storedTheme = localStorage.getItem('color-theme');
if (!storedTheme) {
// Only use system preference if no stored preference exists
const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
document.documentElement.classList.toggle('dark', systemPrefersDark);
localStorage.setItem('color-theme', systemPrefersDark ? 'dark' : 'light');
}
setThemeIcons();
// Add click event to toggle button
document.getElementById('theme-toggle').addEventListener('click', function() {
// Toggle dark class
document.documentElement.classList.toggle('dark');
// Update localStorage
if (document.documentElement.classList.contains('dark')) {
localStorage.setItem('color-theme', 'dark');
} else {
localStorage.setItem('color-theme', 'light');
}
setThemeIcons();
});
// System preference changes are now ignored if there's a stored preference
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function(e) {
if (!localStorage.getItem('color-theme')) {
document.documentElement.classList.toggle('dark', e.matches);
localStorage.setItem('color-theme', e.matches ? 'dark' : 'light');
setThemeIcons();
}
});
});
</script>
<div class="mt-4 text-center text-gray-600 dark:text-gray-400 text-sm">
Make sure your AdGuard Home instance is running and properly configured in the .env file. Make sure your AdGuard Home instance is running and properly configured in the .env file.
<br> <br>
<span class="text-xs">Rules are automatically backed up before any changes.</span> <span class="text-xs">Rules are automatically backed up before any changes.</span>