better titlebar and fixes

This commit is contained in:
2026-01-09 20:35:45 +01:00
parent 1e85de8db6
commit e6c3320a7c
20 changed files with 472 additions and 333 deletions

View File

@@ -1,6 +1,5 @@
;(() => {
const token = localStorage.getItem("token")
if (!token && window.location.pathname !== "/") {
window.location.href = "/"
}
@@ -12,41 +11,61 @@ async function loadMeUI() {
try {
const res = await fetch("/api/me", {
headers: {
Authorization: `Bearer ${token}`,
},
headers: { Authorization: `Bearer ${token}` },
})
if (!res.ok) return
const user = await res.json()
const avatarUrl = user.avatar || "/public/assets/avatar.png"
const navUser = document.getElementById("nav-user")
const navUsername = document.getElementById("nav-username")
const navAvatar = document.getElementById("nav-avatar")
const dropdownAvatar = document.getElementById("dropdown-avatar")
if (!navUser || !navUsername || !navAvatar) return
if (navUser && navUsername && navAvatar) {
navUser.style.display = "flex"
navUsername.textContent = user.username
navAvatar.src = avatarUrl
if (dropdownAvatar) dropdownAvatar.src = avatarUrl
}
navUser.style.display = "flex"
navUsername.textContent = user.username
const titlebarUserBox = document.getElementById("titlebar-user-box")
const titlebarUsername = document.getElementById("titlebar-username")
const titlebarAvatar = document.getElementById("titlebar-avatar")
const titlebarDropdownAvatar = document.getElementById("titlebar-dropdown-avatar")
const titlebarDropdownUsername = document.getElementById("titlebar-dropdown-username")
const avatarUrl = user.avatar || "/public/assets/avatar.png"
navAvatar.src = avatarUrl
if (dropdownAvatar) {
dropdownAvatar.src = avatarUrl
if (titlebarUserBox && titlebarUsername && titlebarAvatar) {
titlebarUserBox.style.display = "flex"
titlebarUsername.textContent = user.username
titlebarAvatar.src = avatarUrl
if (titlebarDropdownAvatar) titlebarDropdownAvatar.src = avatarUrl
if (titlebarDropdownUsername) titlebarDropdownUsername.textContent = user.username
}
setupDropdown()
} catch (e) {
console.error("Failed to load user UI:", e)
}
}
// Variable para saber si el modal ya fue cargado
let settingsModalLoaded = false;
document.getElementById('nav-settings').addEventListener('click', openSettings)
const navSettingsBtn = document.getElementById('nav-settings');
const titlebarSettingsBtn = document.getElementById('titlebar-settings');
if (navSettingsBtn) navSettingsBtn.addEventListener('click', openSettings);
if (titlebarSettingsBtn) titlebarSettingsBtn.addEventListener('click', (e) => {
e.stopPropagation();
openSettings();
document.getElementById("titlebar-dropdown")?.classList.remove("active");
});
async function openSettings() {
if (!settingsModalLoaded) {
@@ -55,63 +74,69 @@ async function openSettings() {
const html = await res.text()
document.body.insertAdjacentHTML('beforeend', html)
settingsModalLoaded = true;
// Esperar un momento para que el DOM se actualice
await new Promise(resolve => setTimeout(resolve, 50));
// Ahora cargar los settings
if (window.toggleSettingsModal) {
await window.toggleSettingsModal(false);
}
if (window.toggleSettingsModal) await window.toggleSettingsModal(false);
} catch (err) {
console.error('Error loading settings modal:', err);
}
} else {
if (window.toggleSettingsModal) {
await window.toggleSettingsModal(false);
}
}
}
function closeSettings() {
const modal = document.getElementById('settings-modal');
if (modal) {
modal.classList.add('hidden');
if (window.toggleSettingsModal) await window.toggleSettingsModal(false);
}
}
function setupDropdown() {
const userAvatarBtn = document.querySelector(".user-avatar-btn")
const navDropdown = document.getElementById("nav-dropdown")
const navLogout = document.getElementById("nav-logout")
if (!userAvatarBtn || !navDropdown || !navLogout) return
if (userAvatarBtn && navDropdown) {
userAvatarBtn.addEventListener("click", (e) => {
e.stopPropagation()
navDropdown.classList.toggle("active")
userAvatarBtn.addEventListener("click", (e) => {
e.stopPropagation()
navDropdown.classList.toggle("active")
})
document.getElementById("titlebar-dropdown")?.classList.remove("active")
})
if (navLogout) {
navLogout.addEventListener("click", () => {
localStorage.removeItem("token")
window.location.href = "/"
})
}
}
const titlebarUserBox = document.getElementById("titlebar-user-box")
const titlebarDropdown = document.getElementById("titlebar-dropdown")
const titlebarLogout = document.getElementById("titlebar-logout")
if (titlebarUserBox && titlebarDropdown) {
titlebarUserBox.addEventListener("click", (e) => {
e.stopPropagation()
titlebarDropdown.classList.toggle("active")
document.getElementById("nav-dropdown")?.classList.remove("active")
})
if (titlebarLogout) {
titlebarLogout.addEventListener("click", (e) => {
e.stopPropagation()
localStorage.removeItem("token")
window.location.href = "/"
})
}
titlebarDropdown.addEventListener("click", (e) => {
e.stopPropagation()
})
}
document.addEventListener("click", (e) => {
if (!navDropdown.contains(e.target)) {
if (navDropdown && !navDropdown.contains(e.target)) {
navDropdown.classList.remove("active")
}
})
navDropdown.addEventListener("click", (e) => {
e.stopPropagation()
})
navLogout.addEventListener("click", () => {
localStorage.removeItem("token")
window.location.href = "/"
})
const dropdownLinks = navDropdown.querySelectorAll("a.dropdown-item")
dropdownLinks.forEach((link) => {
link.addEventListener("click", () => {
navDropdown.classList.remove("active")
})
if (titlebarDropdown && !titlebarDropdown.contains(e.target)) {
titlebarDropdown.classList.remove("active")
}
})
}
@@ -159,7 +184,6 @@ searchWrapper.addEventListener('click', (e) => {
}
});
// Cerrar el buscador si se hace clic fuera
document.addEventListener('click', (e) => {
if (!searchWrapper.contains(e.target)) {
searchWrapper.classList.remove('active-mobile');

View File

@@ -1,7 +1,7 @@
const urlParams = new URLSearchParams(window.location.search);
const reader = document.getElementById('reader');
const panel = document.getElementById('settings-panel');
const overlay = document.getElementById('overlay');
const overlay2 = document.getElementById('overlay');
const settingsBtn = document.getElementById('settings-btn');
const closePanel = document.getElementById('close-panel');
const chapterLabel = document.getElementById('chapter-label');
@@ -665,14 +665,14 @@ document.getElementById('back-btn').addEventListener('click', () => {
// Panel de configuración
settingsBtn.addEventListener('click', () => {
panel.classList.add('open');
overlay.classList.add('active');
overlay2.classList.add('active');
});
closePanel.addEventListener('click', closeSettings);
overlay.addEventListener('click', closeSettings);
overlay2.addEventListener('click', closeSettings);
function closeSettings() {
panel.classList.remove('open');
overlay.classList.remove('active');
overlay2.classList.remove('active');
}
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && panel.classList.contains('open')) {

View File

@@ -1,5 +1,5 @@
const providerSelector = document.getElementById('provider-selector');
const searchInput = document.getElementById('search-input');
const searchInput2 = document.getElementById('search-input');
const resultsContainer = document.getElementById('gallery-results');
let currentPage = 1;
@@ -231,7 +231,7 @@ function showSkeletons(count, append = false) {
async function searchGallery(isLoadMore = false) {
if (isLoading) return;
const query = searchInput.value.trim();
const query = searchInput2.value.trim();
const provider = providerSelector.value;
const page = isLoadMore ? currentPage + 1 : 1;
@@ -351,22 +351,22 @@ async function loadExtensions() {
providerSelector.addEventListener('change', () => {
if (providerSelector.value === 'favorites') {
searchInput.placeholder = "Search in favorites...";
searchInput2.placeholder = "Search in favorites...";
} else {
searchInput.placeholder = "Search in gallery...";
searchInput2.placeholder = "Search in gallery...";
}
searchGallery(false);
});
let searchTimeout;
searchInput.addEventListener('input', () => {
searchInput2.addEventListener('input', () => {
clearTimeout(searchTimeout);
searchTimeout = setTimeout(() => {
searchGallery(false);
}, 500);
});
searchInput.addEventListener('keydown', e => {
searchInput2.addEventListener('keydown', e => {
if (e.key === 'Enter') {
clearTimeout(searchTimeout);
searchGallery(false);