Make chat a page and add sidebar with buttons to cycle through pages on desktop.

This commit is contained in:
天クマ 2026-07-17 13:46:24 -03:00
commit dcd40790e0
5 changed files with 101 additions and 106 deletions

View file

@ -22,6 +22,11 @@
});
</script>
<div class="app-container no-active-chat">
<aside id="desktop-aside">
<button id="chats-sidebar-btn" class="icon-btn mif-qa mif-2x" data-page="chat-page"></button>
<button id="settings-sidebar-btn" class="icon-btn mif-cog mif-2x" data-page="settings-page"></button>
</aside>
<!-- Sidebar -->
<aside class="sidebar">
<header class="sidebar-header">
@ -32,11 +37,6 @@
<h3 id="pandora-username">Pandora User</h3>
</div>
</div>
<div class="header-actions">
<!-- <button class="text-btn" title="New Chat">new chat</button> -->
<button class="text-btn" id="refresh-chats-btn" title="Refresh Chats">refresh</button>
<button class="text-btn" title="Settings">settings</button>
</div>
</header>
<div class="search-container">
@ -68,59 +68,61 @@
</div>
</aside>
<!-- Main Chat Area -->
<main class="chat-area">
<!-- No Chat Selected State -->
<div class="no-chat-state" id="no-chat-state">
<div class="empty-state-content">
<div class="empty-state-icon mif-qa mif-3x">
</div>
<p>Select a contact from the sidebar to view the conversation or start a new chat.</p>
</div>
</div>
<!-- Active Chat State -->
<div class="active-chat-container hidden" id="active-chat-container">
<header class="chat-header">
<div class="active-contact-info">
<!-- <button class="icon-btn back-btn mif-arrow-left mif-2x" id="back-to-sidebar" title="Back to chats"></button> -->
<div class="avatar active-avatar" id="active-chat-avatar">C</div>
<div>
<h3 id="active-chat-name">Contact Name</h3>
<span class="contact-status" id="active-chat-status"></span>
<div class="extra-page" id="chat-page">
<!-- Main Chat Area -->
<main class="chat-area">
<!-- No Chat Selected State -->
<div class="no-chat-state" id="no-chat-state">
<div class="empty-state-content">
<div class="empty-state-icon mif-qa mif-3x">
</div>
<p>Select a contact to view the conversation or start a new chat.</p>
</div>
<div class="chat-actions">
<!-- <button class="icon-btn" title="Search in conversation"><i data-lucide="search"></i></button>
<button class="icon-btn" title="Call"><i data-lucide="phone"></i></button>
<button class="icon-btn" title="Video Call"><i data-lucide="video"></i></button>
<button class="icon-btn" title="More Options"><i data-lucide="more-vertical"></i></button> -->
</div>
</header>
<!-- Messages Area -->
<div class="messages-container" id="messages-container">
<!-- Messages will be dynamically injected here -->
</div>
<!-- Input Panel -->
<footer id="chat-input-panel" class="chat-input-panel">
<div class="input-actions-left">
<button id="chat-bottom-bar-btn" class="icon-btn mif-expand-less mif-3x" title="Expand"></button>
<!-- Active Chat State -->
<div class="active-chat-container hidden" id="active-chat-container">
<header class="chat-header">
<div class="active-contact-info">
<!-- <button class="icon-btn back-btn mif-arrow-left mif-2x" id="back-to-sidebar" title="Back to chats"></button> -->
<div class="avatar active-avatar" id="active-chat-avatar">C</div>
<div>
<h3 id="active-chat-name">Contact Name</h3>
<span class="contact-status" id="active-chat-status"></span>
</div>
</div>
<div class="chat-actions">
<!-- <button class="icon-btn" title="Search in conversation"><i data-lucide="search"></i></button>
<button class="icon-btn" title="Call"><i data-lucide="phone"></i></button>
<button class="icon-btn" title="Video Call"><i data-lucide="video"></i></button>
<button class="icon-btn" title="More Options"><i data-lucide="more-vertical"></i></button> -->
</div>
</header>
<!-- Messages Area -->
<div class="messages-container" id="messages-container">
<!-- Messages will be dynamically injected here -->
</div>
<form class="input-form" id="message-form">
<input type="text" id="message-input" placeholder="Type a message..." autocomplete="off">
<button type="submit" class="send-btn mif-paper-plane mif-3x" id="send-button">
</button>
</form>
</footer>
<!-- Bottom Bar -->
<footer id="chat-bottom-bar" class="chat-expanded-panel alternate-panel collapsed">
<input id="attachment-input" style="display: none;" type="file">
<button id="attachment-btn" class="icon-btn send-btn mif-attachment mif-2x" title="Attach file"></button>
</footer>
</div>
</main>
<!-- Input Panel -->
<footer id="chat-input-panel" class="chat-input-panel">
<div class="input-actions-left">
<button id="chat-bottom-bar-btn" class="icon-btn mif-expand-less mif-3x" title="Expand"></button>
</div>
<form class="input-form" id="message-form">
<input type="text" id="message-input" placeholder="Type a message..." autocomplete="off">
<button type="submit" class="send-btn mif-paper-plane mif-3x" id="send-button">
</button>
</form>
</footer>
<!-- Bottom Bar -->
<footer id="chat-bottom-bar" class="chat-expanded-panel alternate-panel collapsed">
<input id="attachment-input" style="display: none;" type="file">
<button id="attachment-btn" class="icon-btn send-btn mif-attachment mif-2x" title="Attach file"></button>
</footer>
</div>
</main>
</div>
<section class="extra-page" id="settings-page">
<div class="modal-content">
@ -143,7 +145,6 @@
<p class="settings-warning">Note: Requests are sent directly from your browser to the WAHA server. Make sure CORS is enabled on your WAHA instance.</p>
</div>
<footer class="modal-footer">
<button class="btn secondary-btn" id="cancel-settings">Cancel</button>
<button class="btn primary-btn" id="save-settings">Save Config</button>
</footer>
</div>

View file

@ -120,14 +120,6 @@ function setupEventListeners() {
}
});
elements.refreshChatsBtn.addEventListener('click', () => {
elements.refreshChatsBtn.classList.add('spinning');
loadChats()
setTimeout(() => {
elements.refreshChatsBtn.classList.remove('spinning');
}, 600);
});
elements.chatSearch.addEventListener('input', (e) => {
const query = e.target.value.toLowerCase();
const filtered = getChats().filter(chat =>
@ -165,8 +157,12 @@ function setupEventListeners() {
closeActiveChat(false);
});
elements.settingsIconBtn.addEventListener('click', openSettings);
elements.cancelSettingsBtn.addEventListener('click', () => ui.toggleModal(false));
elements.desktopSidebarButtons.forEach(sidebarBtn => {
sidebarBtn.addEventListener('click', () => {
ui.showExtraPage(sidebarBtn.dataset.page);
})
})
elements.saveSettingsBtn.addEventListener('click', saveSettings);
}
@ -271,20 +267,15 @@ async function closeActiveChat(isPopState = false) {
if (window.innerWidth <= 768) {
scrollToList();
setTimeout(() => {
if (!activeChatState) {
elements.appContainer.classList.add('no-active-chat');
// ui.toggleChatState(false);
}
}, 350);
} else {
ui.toggleChatState(false);
}
if (!isPopState) {
// if (window.location.hash.startsWith('#chat-')) {
// history.back();
// }
if (window.location.hash.startsWith('#chat-')) {
history.back();
}
}
}
@ -383,18 +374,13 @@ async function sendFileMessage(file) {
}
}
function openSettings() {
ui.toggleModal(true);
}
function saveSettings() {
config.save(
elements.inputWahaUrl.value,
elements.inputSession.value,
elements.inputApiKey.value
);
ui.toggleModal(false);
location.reload();
loadChats();
checkWahaStatus();
initWebSocket();

View file

@ -1,13 +1,10 @@
import { formatTime, normalizeId } from "./utils.js";
import { waha } from "./waha.js";
import { config } from "./config.js";
import { getChatPicture, getMessage, getMedia, getMoreChatMessages } from "./storage.js";
export const elements = {
chatList: document.getElementById('chat-list'),
chatsLoader: document.getElementById('chats-loader'),
chatSearch: document.getElementById('chat-search'),
refreshChatsBtn: document.getElementById('refresh-chats-btn'),
backendStatusText: document.getElementById('backend-status-text'),
apiStatusIndicator: document.querySelector('.pulse-dot'),
noChatState: document.getElementById('no-chat-state'),
@ -21,8 +18,7 @@ export const elements = {
sidebar: document.querySelector('.sidebar'),
appContainer: document.querySelector('.app-container'),
settingsModal: document.getElementById('settings-page'),
settingsIconBtn: document.querySelector('.header-actions button[title="Settings"]'),
cancelSettingsBtn: document.getElementById('cancel-settings'),
settingsIconBtn: document.getElementById('settings-sidebar-btn'),
saveSettingsBtn: document.getElementById('save-settings'),
inputWahaUrl: document.getElementById('settings-waha-url'),
inputSession: document.getElementById('settings-session'),
@ -33,18 +29,19 @@ export const elements = {
chatInputPanel: document.getElementById('chat-input-panel'),
attachmentInput: document.getElementById('attachment-input'),
attachmentBtn: document.getElementById('attachment-btn'),
extraPages: document.querySelectorAll('.extra-page'),
desktopSidebarButtons: document.querySelectorAll("#desktop-aside button")
};
export const ui = {
/**
* Show or hide Settings connection modal
*/
toggleModal(show) {
if (show) {
elements.settingsModal.scrollTo();
} else {
elements.sidebar.scrollTo();
}
showExtraPage(pageId) {
elements.extraPages.forEach(page => {
if (page.id != pageId) {
page.style.display = "none";
} else {
page.style.display = "flex";
}
})
},
/**

View file

@ -1,7 +1,3 @@
body {
background-color: #4e8ba6;
}
.dots {
position: relative;
width: 100%;

View file

@ -364,6 +364,16 @@ input:focus {
to { transform: rotate(360deg); }
}
/* Desktop aside */
#desktop-aside {
height: 100%;
background-color: black;
border-right: 1px solid var(--border-color);
display: flex;
flex-direction: column;
padding: .2em;
}
/* Sidebar Footer */
.sidebar-footer {
padding: 14px 20px;
@ -383,14 +393,14 @@ input:focus {
height: 8px;
background-color: var(--online-color);
border-radius: 50%;
box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.7);
box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7);
animation: pulse 1.8s infinite;
}
@keyframes pulse {
0% {
transform: scale(0.95);
box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.7);
box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7);
}
70% {
transform: scale(1);
@ -740,6 +750,7 @@ input:focus {
/* Extra Pages */
.extra-page {
display: none;
width: 100%;
}
.extra-page-content {
@ -747,6 +758,10 @@ input:focus {
color: var(--text-secondary);
}
#chat-page {
display: flex;
}
@media (max-width: 768px) {
.app-container {
width: 100%;
@ -806,11 +821,6 @@ input:focus {
overflow-y: auto;
}
/* Disable scrolling to active chat if none is selected */
/* .app-container.no-active-chat .chat-area {
display: none !important;
} */
.back-btn {
display: flex;
margin-right: 12px;
@ -823,6 +833,10 @@ input:focus {
.message-image-attachement {
max-height: 20em;
}
#desktop-aside {
display: none;
}
}
/* Modal Styling */
@ -847,6 +861,7 @@ input:focus {
backdrop-filter: var(--glass-blur);
display: flex;
flex-direction: column;
height: 100%;
}
.modal-header {