[Chore] Sync timer to actual imap-reload

This commit is contained in:
ClaraCrazy 2025-12-31 22:40:53 +01:00
parent 710560c410
commit 72c22f9815
No known key found for this signature in database
GPG key ID: EBBC896ACB497011
5 changed files with 65 additions and 13 deletions

5
app.js
View file

@ -43,6 +43,11 @@ const mailProcessingService = new MailProcessingService(
) )
debug('Mail processing service initialized') debug('Mail processing service initialized')
// Set up timer sync broadcasting after IMAP is ready
imapService.on(ImapService.EVENT_INITIAL_LOAD_DONE, () => {
clientNotification.startTimerSync(imapService)
})
// Track IMAP initialization state // Track IMAP initialization state
let isImapReady = false let isImapReady = false
app.set('isImapReady', false) app.set('isImapReady', false)

View file

@ -97,6 +97,7 @@ class ImapService extends EventEmitter {
this.connection = null this.connection = null
this.initialLoadDone = false this.initialLoadDone = false
this.loadingInProgress = false this.loadingInProgress = false
this.lastRefreshTime = null
} }
async connectAndLoadMessages() { async connectAndLoadMessages() {
@ -157,8 +158,14 @@ class ImapService extends EventEmitter {
// for new mails on the server. This is done only after all the mails have been loaded for the // for new mails on the server. This is done only after all the mails have been loaded for the
// first time. (Note: set the refresh higher than the time it takes to download the mails). // first time. (Note: set the refresh higher than the time it takes to download the mails).
if (this.config.imap.refreshIntervalSeconds) { if (this.config.imap.refreshIntervalSeconds) {
// Track when refreshes happen
this.lastRefreshTime = Date.now()
setInterval( setInterval(
() => this._loadMailSummariesAndEmitAsEvents(), () => {
this.lastRefreshTime = Date.now()
this._loadMailSummariesAndEmitAsEvents()
},
this.config.imap.refreshIntervalSeconds * 1000 this.config.imap.refreshIntervalSeconds * 1000
) )
} }
@ -306,6 +313,20 @@ class ImapService extends EventEmitter {
} }
} }
/**
* Get seconds remaining until next IMAP refresh
* @returns {number} Seconds until next refresh, or null if not started
*/
getSecondsUntilNextRefresh() {
if (!this.lastRefreshTime || !this.config.imap.refreshIntervalSeconds) {
return null
}
const elapsed = (Date.now() - this.lastRefreshTime) / 1000
const remaining = Math.max(0, this.config.imap.refreshIntervalSeconds - elapsed)
return Math.ceil(remaining)
}
/** /**
* Helper method because ImapSimple#search also fetches each message. We just need the uids here. * Helper method because ImapSimple#search also fetches each message. We just need the uids here.
* *

View file

@ -9,9 +9,13 @@ class ClientNotification extends EventEmitter {
constructor() { constructor() {
super(); super();
this.pendingNotifications = new Map(); // address -> count this.pendingNotifications = new Map(); // address -> count
this.io = null;
this.imapService = null;
this.timerSyncInterval = null;
} }
use(io) { use(io) {
this.io = io;
io.on('connection', socket => { io.on('connection', socket => {
debug(`[SOCKET] New connection: id=${socket.id}`); debug(`[SOCKET] New connection: id=${socket.id}`);
socket.on('sign in', address => { socket.on('sign in', address => {
@ -24,6 +28,25 @@ class ClientNotification extends EventEmitter {
}) })
} }
startTimerSync(imapService) {
this.imapService = imapService;
// Broadcast timer sync every second to all connected clients
if (this.timerSyncInterval) {
clearInterval(this.timerSyncInterval);
}
this.timerSyncInterval = setInterval(() => {
const secondsRemaining = this.imapService.getSecondsUntilNextRefresh();
if (secondsRemaining !== null && this.io) {
// Broadcast to all connected clients
this.io.emit('refresh-timer-sync', secondsRemaining);
}
}, 1000);
debug('Started timer sync broadcasting');
}
_signIn(socket, address) { _signIn(socket, address) {
debug(`socketio signed in: ${address}`) debug(`socketio signed in: ${address}`)

View file

@ -31,6 +31,13 @@ function enableNewMessageNotifications(address, reloadPage) {
socket.on('new emails', () => { socket.on('new emails', () => {
showNewMailsNotification(address, reloadPage) showNewMailsNotification(address, reloadPage)
}) })
// Listen for timer sync from server
socket.on('refresh-timer-sync', (secondsRemaining) => {
if (window.updateRefreshTimer && typeof window.updateRefreshTimer === 'function') {
window.updateRefreshTimer(secondsRemaining)
}
})
} }
function enableNotifications() { function enableNotifications() {

View file

@ -351,19 +351,15 @@ document.addEventListener('DOMContentLoaded', () => {
const refreshTimer = document.getElementById('refreshTimer'); const refreshTimer = document.getElementById('refreshTimer');
if (!refreshTimer || !refreshInterval) return; if (!refreshTimer || !refreshInterval) return;
let secondsLeft = refreshInterval; // Function to update timer display
window.updateRefreshTimer = function(secondsLeft) {
function updateTimer() { if (refreshTimer) {
refreshTimer.textContent = secondsLeft; refreshTimer.textContent = secondsLeft;
secondsLeft--;
if (secondsLeft < 0) {
secondsLeft = refreshInterval;
} }
} };
updateTimer(); // Initial update // Initialize with the configured interval
setInterval(updateTimer, 1000); refreshTimer.textContent = refreshInterval;
} }
// Expose utilities and run them // Expose utilities and run them