mirror of
https://github.com/ChrispyBacon-dev/DockFlare.git
synced 2026-04-26 10:50:43 +00:00
several webmail und mail manager fixes
This commit is contained in:
parent
5e0ddbd46b
commit
35b449a478
7 changed files with 62 additions and 13 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 }}
|
||||
<span class="ml-auto text-muted-foreground flex gap-1">
|
||||
<span v-if="f.total_count > 0" class="ml-auto text-muted-foreground flex gap-1">
|
||||
<span v-if="f.unread_count" class="font-bold">{{ f.unread_count }} /</span>
|
||||
<span>{{ f.total_count || 0 }}</span>
|
||||
<span>{{ f.total_count }}</span>
|
||||
</span>
|
||||
</TooltipContent>
|
||||
</TooltipPortal>
|
||||
|
|
@ -199,13 +199,14 @@ const confirmEdit = async () => {
|
|||
<component :is="getIcon(f.name)" class="size-4 flex-shrink-0" :style="f.color ? `color:${f.color}` : ''" />
|
||||
<span class="truncate">{{ f.name }}</span>
|
||||
<span
|
||||
v-if="f.total_count > 0"
|
||||
:class="cn(
|
||||
'ml-auto text-xs flex-shrink-0 flex gap-1',
|
||||
store.currentFolder === f.name ? 'text-primary-foreground' : 'text-muted-foreground',
|
||||
)"
|
||||
>
|
||||
<span v-if="f.unread_count" class="font-bold">{{ f.unread_count }} /</span>
|
||||
<span>{{ f.total_count || 0 }}</span>
|
||||
<span>{{ f.total_count }}</span>
|
||||
</span>
|
||||
</button>
|
||||
<!-- Custom folder actions — absolutely positioned so they don't affect count alignment -->
|
||||
|
|
@ -251,6 +252,12 @@ const confirmEdit = async () => {
|
|||
:style="`background:${c}; border-color:${newFolderColor === c ? '#000' : 'transparent'}`"
|
||||
@click="newFolderColor = newFolderColor === c ? '' : c"
|
||||
/>
|
||||
<button
|
||||
class="h-5 w-5 rounded-full border-2 text-xs flex items-center justify-center text-muted-foreground hover:bg-accent"
|
||||
:style="`border-color:${!newFolderColor ? '#888' : 'transparent'}`"
|
||||
title="No colour"
|
||||
@click="newFolderColor = ''"
|
||||
>✕</button>
|
||||
</div>
|
||||
<div class="flex gap-1 justify-end">
|
||||
<button class="text-xs px-2 py-1 rounded hover:bg-accent text-muted-foreground" @click="cancelNewFolder">Cancel</button>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
>
|
||||
<DropdownMenuItem
|
||||
v-if="props.message?.is_read"
|
||||
class="relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent"
|
||||
@click="markUnread"
|
||||
>
|
||||
<MailOpen class="mr-2 size-4" />
|
||||
Mark as unread
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
v-else
|
||||
class="relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent"
|
||||
@click="markRead"
|
||||
>
|
||||
<MailOpen class="mr-2 size-4" />
|
||||
Mark as read
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
class="relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent"
|
||||
@click="toggleStar"
|
||||
|
|
|
|||
|
|
@ -57,6 +57,11 @@ export function useMailPolling() {
|
|||
const payload = mRes.data
|
||||
mailStore.messages = Array.isArray(payload) ? payload : payload.items || []
|
||||
} catch { /* network error — skip */ }
|
||||
|
||||
try {
|
||||
const fRes = await mailApi.getFolders(s.address)
|
||||
mailStore.folders = fRes.data
|
||||
} catch { /* network error — skip */ }
|
||||
}
|
||||
|
||||
if (Notification.permission === 'granted') {
|
||||
|
|
|
|||
|
|
@ -97,15 +97,16 @@ watch(() => 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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue