refactor: split stores and use events

Signed-off-by: Sebastian <krupinski01@gmail.com>
This commit is contained in:
2026-05-14 22:26:45 -04:00
parent 46632d2454
commit 232f588225
19 changed files with 1808 additions and 1210 deletions

View File

@@ -38,34 +38,26 @@ const LONG_PRESS_MS = 450
const selectedIdSet = computed(() => new Set(props.selectionList))
const isOpened = (message: EntityObject): boolean => {
if (!props.selectedMessage) return false
return (
message.provider === props.selectedMessage.provider &&
message.service === props.selectedMessage.service &&
message.collection === props.selectedMessage.collection &&
message.identifier === props.selectedMessage.identifier
)
}
const isSelected = (message: EntityObject): boolean => {
return selectedIdSet.value.has(
`${message.provider}:${String(message.service)}:${String(message.collection)}:${String(message.identifier)}` as EntityIdentifier,
)
}
// Check if message is unread
const isUnread = (message: EntityObject): boolean => {
return !message.properties.flags?.read
}
// Check if message is flagged
const isFlagged = (message: EntityObject): boolean => {
return message.properties.flags?.flagged || false
}
const currentMessages = computed(() => props.messages ?? [])
const getMessageTimestamp = (message: EntityObject): string | null => {
return message.properties.received
|| message.properties.sent
|| message.modified
|| message.created
|| null
}
const getMessageTimeValue = (message: EntityObject): number => {
const timestamp = getMessageTimestamp(message)
if (!timestamp) {
return 0
}
const timeValue = new Date(timestamp).getTime()
return Number.isNaN(timeValue) ? 0 : timeValue
}
const selectionCount = computed(() => props.selectionList.length)
const hasSelection = computed(() => selectionCount.value > 0)
@@ -74,11 +66,45 @@ const allCurrentMessagesSelected = computed(() => {
return currentMessages.value.length > 0 && currentMessages.value.every(message => isSelected(message))
})
// Sorted messages (newest first)
const sortedMessages = computed(() => {
return [...currentMessages.value].sort((a, b) => {
const dateA = getMessageTimeValue(a)
const dateB = getMessageTimeValue(b)
return dateB - dateA
})
})
// Read/Unread counts from collection properties
const unreadCount = computed(() => {
return props.selectedCollection?.properties.unread ?? 0
})
const totalCount = computed(() => {
return props.selectedCollection?.properties.total ?? 0
})
// True only when the collection explicitly provides total/unread counts
const hasCountData = computed(() => {
return props.selectedCollection?.properties.total != null
})
const isOpened = (message: EntityObject): boolean => {
if (!props.selectedMessage) return false
return (message.identifier === props.selectedMessage.identifier)
}
const isSelected = (message: EntityObject): boolean => {
return selectedIdSet.value.has(message.identifier)
}
// Format date for display
const formatDate = (date: Date | string | null | undefined): string => {
if (!date) return ''
const messageDate = new Date(date)
if (Number.isNaN(messageDate.getTime())) return ''
const now = new Date()
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())
const yesterday = new Date(today)
@@ -121,11 +147,24 @@ const truncate = (text: string | null | undefined, length: number = 100): string
return text.length > length ? text.substring(0, length) + '...' : text
}
const isSelectionControlClick = (event: MouseEvent | KeyboardEvent): boolean => {
return event.target instanceof Element && event.target.closest('.message-selection-checkbox') !== null
}
const handleSelectionToggle = (message: EntityObject) => {
emit('toggleSelection', message)
}
const handleMessageMouseClick = (event: MouseEvent | KeyboardEvent, message: EntityObject) => {
if (isSelectionControlClick(event)) {
return
}
if (suppressNextClick.value) {
suppressNextClick.value = false
return
}
if (event.shiftKey && !props.selectionMode) {
event.preventDefault()
event.stopPropagation()
@@ -138,11 +177,6 @@ const handleMessageMouseClick = (event: MouseEvent | KeyboardEvent, message: Ent
return
}
if (suppressNextClick.value) {
suppressNextClick.value = false
return
}
if (props.selectionMode) {
emit('toggleSelection', message)
return
@@ -152,6 +186,10 @@ const handleMessageMouseClick = (event: MouseEvent | KeyboardEvent, message: Ent
}
const handleMessageMouseDown = (event: MouseEvent, message: EntityObject) => {
if (isSelectionControlClick(event)) {
return
}
if (!event.shiftKey || props.selectionMode) {
return
}
@@ -200,29 +238,6 @@ onBeforeUnmount(() => {
const handleSelectAllToggle = (value: boolean | null) => {
emit('toggleSelectAll', value === true)
}
// Sorted messages (newest first)
const sortedMessages = computed(() => {
return [...currentMessages.value].sort((a, b) => {
const dateA = a.properties.date ? new Date(a.properties.date).getTime() : 0
const dateB = b.properties.date ? new Date(b.properties.date).getTime() : 0
return dateB - dateA
})
})
// Read/Unread counts from collection properties
const unreadCount = computed(() => {
return props.selectedCollection?.properties.unread ?? 0
})
const totalCount = computed(() => {
return props.selectedCollection?.properties.total ?? 0
})
// True only when the collection explicitly provides total/unread counts
const hasCountData = computed(() => {
return props.selectedCollection?.properties.total != null
})
</script>
<template>
@@ -282,7 +297,6 @@ const hasCountData = computed(() => {
size="small"
icon="mdi-close"
variant="text"
:disabled="!hasSelection"
@click="emit('clearSelection')"
>
<v-icon>mdi-close</v-icon>
@@ -320,13 +334,13 @@ const hasCountData = computed(() => {
>
<template v-slot:default="{ item: message }">
<v-list-item
:key="`${message.provider}:${message.service}:${message.collection}:${message.identifier}`"
:key="message.identifier"
class="message-item"
:class="{
'opened': isOpened(message),
'selected': isSelected(message),
'selection-mode': selectionMode,
'unread': isUnread(message)
'unread': !message.properties.isRead
}"
@mousedown="handleMessageMouseDown($event, message)"
@click="handleMessageMouseClick($event, message)"
@@ -360,7 +374,7 @@ const hasCountData = computed(() => {
{{ message.properties.from?.label || message.properties.from?.address || 'Unknown Sender' }}
</span>
<span class="text-caption text-medium-emphasis ml-2">
{{ formatDate(message.properties.date) }}
{{ formatDate(getMessageTimestamp(message)) }}
</span>
</v-list-item-title>
@@ -369,13 +383,13 @@ const hasCountData = computed(() => {
</v-list-item-subtitle>
<v-list-item-subtitle class="text-caption text-truncate">
{{ truncate(message.properties.snippet, 80) }}
{{ '' }}
</v-list-item-subtitle>
<template v-slot:append>
<div class="d-flex flex-column align-center">
<v-icon
v-if="isFlagged(message)"
v-if="message.properties.isFlagged"
size="small"
color="warning"
class="mb-1"
@@ -383,7 +397,7 @@ const hasCountData = computed(() => {
mdi-star
</v-icon>
<v-icon
v-if="message.properties.attachments && message.properties.attachments.length > 0"
v-if="message.properties.hasAttachments"
size="small"
color="grey"
>