[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')
// Set up timer sync broadcasting after IMAP is ready
imapService.on(ImapService.EVENT_INITIAL_LOAD_DONE, () => {
clientNotification.startTimerSync(imapService)
})
// Track IMAP initialization state
let isImapReady = false
app.set('isImapReady', false)

View file

@ -97,6 +97,7 @@ class ImapService extends EventEmitter {
this.connection = null
this.initialLoadDone = false
this.loadingInProgress = false
this.lastRefreshTime = null
}
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
// first time. (Note: set the refresh higher than the time it takes to download the mails).
if (this.config.imap.refreshIntervalSeconds) {
// Track when refreshes happen
this.lastRefreshTime = Date.now()
setInterval(
() => this._loadMailSummariesAndEmitAsEvents(),
() => {
this.lastRefreshTime = Date.now()
this._loadMailSummariesAndEmitAsEvents()
},
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.
*

View file

@ -9,9 +9,13 @@ class ClientNotification extends EventEmitter {
constructor() {
super();
this.pendingNotifications = new Map(); // address -> count
this.io = null;
this.imapService = null;
this.timerSyncInterval = null;
}
use(io) {
this.io = io;
io.on('connection', socket => {
debug(`[SOCKET] New connection: id=${socket.id}`);
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) {
debug(`socketio signed in: ${address}`)

View file

@ -31,6 +31,13 @@ function enableNewMessageNotifications(address, reloadPage) {
socket.on('new emails', () => {
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() {
@ -54,4 +61,4 @@ function enableNotifications() {
// Finally, if the user has denied notifications and you
// want to be respectful there is no need to bother them any more.
}
}

View file

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