diff --git a/dockflare/app/static/js/main.js b/dockflare/app/static/js/main.js index 182913f..d14a31d 100644 --- a/dockflare/app/static/js/main.js +++ b/dockflare/app/static/js/main.js @@ -1460,7 +1460,7 @@ document.addEventListener('DOMContentLoaded', function() { fixResourcesAndBase(); themeManager.initialize(); initializeAllTomSelects(); - + const manualServiceTypeSelect = document.getElementById('manual_service_type'); if (manualServiceTypeSelect) { manualServiceTypeSelect.addEventListener('change', updateManualRuleServiceFields); diff --git a/dockflare/app/web/email_routes.py b/dockflare/app/web/email_routes.py index 3ad784a..a6446b6 100644 --- a/dockflare/app/web/email_routes.py +++ b/dockflare/app/web/email_routes.py @@ -1075,7 +1075,7 @@ def internal_mail_config(): 'outbound_worker_url': d.get('outbound_worker_url', ''), 'outbound_auth_secret': d.get('outbound_auth_secret', ''), 'mailboxes': { - addr: {'display_name': m.get('display_name', '')} + addr: {'display_name': m.get('display_name', ''), 'quota_bytes': m.get('quota_bytes', 10737418240)} for addr, m in d.get('mailboxes', {}).items() } } diff --git a/mail-manager/app/api/routes.py b/mail-manager/app/api/routes.py index d27ab4a..7f3c925 100644 --- a/mail-manager/app/api/routes.py +++ b/mail-manager/app/api/routes.py @@ -181,6 +181,11 @@ def get_mailboxes(): mb['received_count'] = received.get(addr, 0) mb['sent_count'] = sent.get(addr, 0) mb['storage_bytes'] = storage.get(addr, 0) + if mb['quota_bytes'] and mb['quota_bytes'] > 0: + if storage.get(addr, 0) <= mb['quota_bytes'] and mb['quota_exceeded_count'] > 0: + db.execute("UPDATE mailboxes SET quota_exceeded_count=0 WHERE address=?", (addr,)) + mb['quota_exceeded_count'] = 0 + db.commit() return jsonify(mailboxes) diff --git a/webmail/src/components/mail/FolderNav.vue b/webmail/src/components/mail/FolderNav.vue index 7cf5ace..b7771b5 100644 --- a/webmail/src/components/mail/FolderNav.vue +++ b/webmail/src/components/mail/FolderNav.vue @@ -145,9 +145,9 @@ const confirmEdit = async () => { class="z-50 rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md flex items-center gap-4" > {{ f.name }} - + {{ f.unread_count }} / - {{ f.total_count || 0 }} + {{ f.total_count }} @@ -199,13 +199,14 @@ const confirmEdit = async () => { {{ f.name }} {{ f.unread_count }} / - {{ f.total_count || 0 }} + {{ f.total_count }} @@ -251,6 +252,12 @@ const confirmEdit = async () => { :style="`background:${c}; border-color:${newFolderColor === c ? '#000' : 'transparent'}`" @click="newFolderColor = newFolderColor === c ? '' : c" /> +
diff --git a/webmail/src/components/mail/MessageDisplay.vue b/webmail/src/components/mail/MessageDisplay.vue index e56f8e3..11c69e0 100644 --- a/webmail/src/components/mail/MessageDisplay.vue +++ b/webmail/src/components/mail/MessageDisplay.vue @@ -153,6 +153,8 @@ const trash = async () => { await mailApi.deleteMessage(store.currentMailbox, props.message.id) store.messages = store.messages.filter((m: any) => m.id !== props.message!.id) store.currentMessage = null + const fRes = await mailApi.getFolders(store.currentMailbox) + store.folders = fRes.data } catch (e) { console.error('Failed to trash message', e) } @@ -164,12 +166,28 @@ const markUnread = async () => { await mailApi.updateMessage(store.currentMailbox, props.message.id, { is_read: false }) const idx = store.messages.findIndex((m: any) => m.id === props.message!.id) if (idx !== -1) store.messages[idx] = { ...store.messages[idx], is_read: 0 } - store.currentMessage = null + store.currentMessage = { ...store.currentMessage, is_read: 0 } + const fRes = await mailApi.getFolders(store.currentMailbox) + store.folders = fRes.data } catch (e) { console.error('Failed to mark unread', e) } } +const markRead = async () => { + if (!props.message || !store.currentMailbox) return + try { + await mailApi.updateMessage(store.currentMailbox, props.message.id, { is_read: true }) + const idx = store.messages.findIndex((m: any) => m.id === props.message!.id) + if (idx !== -1) store.messages[idx] = { ...store.messages[idx], is_read: 1 } + store.currentMessage = { ...store.currentMessage, is_read: 1 } + const fRes = await mailApi.getFolders(store.currentMailbox) + store.folders = fRes.data + } catch (e) { + console.error('Failed to mark read', e) + } +} + const toggleStar = async () => { if (!props.message || !store.currentMailbox) return const newVal = props.message.is_starred ? 0 : 1 @@ -192,6 +210,8 @@ const moveToFolder = async (targetFolder: any) => { }) store.messages = store.messages.filter((m: any) => m.id !== props.message!.id) store.currentMessage = null + const fRes = await mailApi.getFolders(store.currentMailbox) + store.folders = fRes.data } catch (e) { console.error('Failed to move message', e) } @@ -401,12 +421,21 @@ const sendInlineReply = async () => { class="z-50 min-w-[160px] rounded-md border bg-popover p-1 text-popover-foreground shadow-md" > Mark as unread + + + Mark as read + store.sortOrder, () => { }) watch(() => store.currentMessage, async (msg) => { - if (!msg || msg.attachments !== undefined) return + if (!msg) return try { - const res = await mailApi.getMessage(store.currentMailbox, msg.id) - const fullMsg = res.data - store.currentMessage = fullMsg - const idx = store.messages.findIndex((m: any) => m.id === msg.id) - if (idx !== -1) { - store.messages[idx] = fullMsg + let fullMsg = msg + + if (msg.attachments === undefined) { + const res = await mailApi.getMessage(store.currentMailbox, msg.id) + fullMsg = res.data + store.currentMessage = fullMsg + if (idx !== -1) store.messages[idx] = fullMsg } if (!fullMsg.is_read) { @@ -114,6 +115,8 @@ watch(() => store.currentMessage, async (msg) => { store.messages[idx] = { ...store.messages[idx], is_read: 1 } } store.currentMessage = { ...store.currentMessage, is_read: 1 } + const fRes = await mailApi.getFolders(store.currentMailbox) + store.folders = fRes.data } } catch (e) { console.error('Failed to load message', e)