Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions app/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='assets/img/ico_main_25.ico') }}">
</head>
<body data-theme="{{ current_user.theme_preference if current_user.is_authenticated else 'dark' }}">
{% if current_user.is_authenticated %}
<nav>
<div class="nav-brand">
<a href="{{ url_for('dashboard') }}">DirectAdmin 📧 Forwarder</a>
Expand All @@ -30,7 +31,9 @@
<a href="{{ url_for('auth.logout') }}">Logout</a>
</div>
</nav>
{% endif %}

<main class="site-main">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
Expand All @@ -40,6 +43,7 @@
{% endwith %}

{% block content %}{% endblock %}
</main>

<footer class="site-footer">
<p>Created by <a href="https://github.com/GitTimeraider" target="_blank" rel="noopener noreferrer">GitTimeraider</a></p>
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Flask==3.1.3
Flask-SQLAlchemy==3.1.1
Flask-Login==0.6.3
gunicorn==26.0.0
gunicorn==26.1.0
Werkzeug==3.1.8
pyotp==2.10.0
qrcode==8.2
Expand Down
85 changes: 43 additions & 42 deletions static/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,60 +4,61 @@ document.addEventListener('DOMContentLoaded', function() {
const navLinks = document.getElementById('navLinks');
const body = document.body;

// Create overlay element
const overlay = document.createElement('div');
overlay.className = 'nav-overlay';
document.body.appendChild(overlay);
// Nav is only rendered for authenticated users (e.g. not on the login page)
if (hamburger && navLinks) {
// Create overlay element
const overlay = document.createElement('div');
overlay.className = 'nav-overlay';
document.body.appendChild(overlay);

// Toggle menu function
function toggleMenu() {
hamburger.classList.toggle('active');
navLinks.classList.toggle('active');
overlay.classList.toggle('active');
body.classList.toggle('menu-open');
}
// Toggle menu function
function toggleMenu() {
hamburger.classList.toggle('active');
navLinks.classList.toggle('active');
overlay.classList.toggle('active');
body.classList.toggle('menu-open');
}

// Hamburger click
if (hamburger) {
// Hamburger click
hamburger.addEventListener('click', toggleMenu);
}

// Overlay click (close menu)
overlay.addEventListener('click', function() {
if (navLinks.classList.contains('active')) {
toggleMenu();
}
});

// Close menu when clicking a link
const navLinksItems = navLinks.querySelectorAll('a');
navLinksItems.forEach(link => {
link.addEventListener('click', function() {
if (window.innerWidth <= 768) {
// Overlay click (close menu)
overlay.addEventListener('click', function() {
if (navLinks.classList.contains('active')) {
toggleMenu();
}
});
});

// Handle window resize
let resizeTimer;
window.addEventListener('resize', function() {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function() {
if (window.innerWidth > 768) {
// Reset menu state on desktop
hamburger.classList.remove('active');
navLinks.classList.remove('active');
overlay.classList.remove('active');
body.classList.remove('menu-open');
}
}, 250);
});
// Close menu when clicking a link
const navLinksItems = navLinks.querySelectorAll('a');
navLinksItems.forEach(link => {
link.addEventListener('click', function() {
if (window.innerWidth <= 768) {
toggleMenu();
}
});
});

// Handle window resize
let resizeTimer;
window.addEventListener('resize', function() {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function() {
if (window.innerWidth > 768) {
// Reset menu state on desktop
hamburger.classList.remove('active');
navLinks.classList.remove('active');
overlay.classList.remove('active');
body.classList.remove('menu-open');
}
}, 250);
});
}

// Theme persistence - apply theme from localStorage if different from server preference
const savedTheme = localStorage.getItem('theme-preference');
const currentTheme = body.getAttribute('data-theme');

if (savedTheme && savedTheme !== currentTheme) {
body.setAttribute('data-theme', savedTheme);
}
Expand Down
Loading