diff --git a/index.html b/index.html index 1f455f7..d1510e7 100644 --- a/index.html +++ b/index.html @@ -106,6 +106,7 @@ diff --git a/js/app.js b/js/app.js index 6882d9f..b8f0201 100644 --- a/js/app.js +++ b/js/app.js @@ -3,7 +3,7 @@ import { waha } from "./waha.js"; import { ui, elements } from "./ui.js"; import { websocket } from "./websocket.js"; import { compensateMessageOrdering, debounce, formatTime, normalizeId } from "./utils.js"; -import { fetchChats, getAppUser, getChatMessages, getChatPicture, getChats, getUser, getUserAbout, sendStatus, updateOnlineStatus } from "./storage.js"; +import { fetchChats, getAppUser, getChatMessages, getChatPicture, getChats, getUser, getUserAbout, markRead, sendStatus, updateOnlineStatus } from "./storage.js"; import { upsertMessages } from "./db.js"; import { showNotification } from "./notification.js"; @@ -181,6 +181,9 @@ function setupEventListeners() { if (e.target == e.currentTarget) ui.toggleChatBottomBar(); }); + elements.markreadBtn.addEventListener('click', () => { + markRead(activeChatState.id); + }) elements.attachmentBtn.addEventListener('click', () => { elements.attachmentInput.click(); }) diff --git a/js/db.js b/js/db.js index f1eb2a2..1d2997b 100644 --- a/js/db.js +++ b/js/db.js @@ -107,6 +107,19 @@ export async function loadChatsSorted() { }); } +export async function loadChat(chatId) { + const db = await openDb(); + + return new Promise((resolve, reject) => { + const tx = db.transaction("chats", "readonly"); + const store = tx.objectStore("chats"); + const req = store.get(chatId); + + tx.oncomplete = () => resolve(req.result) + tx.onerror = () => reject(req.error); + }); +} + function mapMessage(m) { const from = normalizeId(m.from); const to = normalizeId(m.to); diff --git a/js/storage.js b/js/storage.js index 238b4b9..73986d9 100644 --- a/js/storage.js +++ b/js/storage.js @@ -1,4 +1,4 @@ -import { loadChatsSorted, loadLatestMessages, loadMedia, loadOlderMessages, upsertChats, upsertMedia, upsertMessages } from "./db.js"; +import { loadChat, loadChatsSorted, loadLatestMessages, loadMedia, loadOlderMessages, upsertChats, upsertMedia, upsertMessages } from "./db.js"; import { waha } from "./waha.js"; let online = false; @@ -147,4 +147,14 @@ export async function sendStatus(text) { success: false } } +} + +export async function markRead(chatId) { + if (online) { + await waha.readChat(chatId); + } + + const chat = await loadChat(chatId); + chat.unreadCount = 0; + upsertMessages([chat]); } \ No newline at end of file diff --git a/js/ui.js b/js/ui.js index 5ffe494..2328e78 100644 --- a/js/ui.js +++ b/js/ui.js @@ -32,6 +32,7 @@ export const elements = { chatInputPanel: document.getElementById('chat-input-panel'), attachmentInput: document.getElementById('attachment-input'), attachmentBtn: document.getElementById('attachment-btn'), + markreadBtn: document.getElementById('markread-btn'), extraPages: document.querySelectorAll('.extra-page'), desktopSidebarButtons: document.querySelectorAll("#desktop-aside button"), contentUserName: document.querySelectorAll('[data-content="app-user"]'), diff --git a/js/waha.js b/js/waha.js index 2c5c077..6410201 100644 --- a/js/waha.js +++ b/js/waha.js @@ -1,4 +1,5 @@ import { config } from "./config.js"; +import { showNotification } from "./notification.js"; import { getBase64 } from "./utils.js"; async function request(path, options = {}) { @@ -24,6 +25,8 @@ async function request(path, options = {}) { } catch (_) { errorDetail = await response.text().catch(() => ''); } + + showNotification("API Error", `WAHA API returned ${response.status}: ${response.statusText} — ${errorDetail}`, 2000); throw new Error(`WAHA API returned ${response.status}: ${response.statusText} — ${errorDetail}`); } return response.json(); diff --git a/style.css b/style.css index 9cd1117..e27d445 100644 --- a/style.css +++ b/style.css @@ -233,10 +233,14 @@ input:focus { .icon-btn:hover { background: rgba(255, 255, 255, 0.08); - color: var(--text-primary); + color: var(--bg-main); border-color: var(--border-hover); } +.icon-btn:hover::before { + color: var(--bg-main); +} + .icon-btn:active { transform: translateY(0); }