From 5a58c3c7ac34e585f28b190baf1c737995ccdf36 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sun, 17 May 2026 17:52:16 -0400 Subject: [PATCH] refactor: clean up event methods Signed-off-by: Sebastian --- src/components/MessageComposer.vue | 2 - src/components/MessageList.vue | 161 ++++++++++++----------------- src/pages/MailPage.vue | 137 ++++++++++++------------ src/stores/mailStore.ts | 29 ++---- src/stores/mailUiStore.ts | 41 ++++---- 5 files changed, 160 insertions(+), 210 deletions(-) diff --git a/src/components/MessageComposer.vue b/src/components/MessageComposer.vue index 5ab7049..b221085 100644 --- a/src/components/MessageComposer.vue +++ b/src/components/MessageComposer.vue @@ -26,7 +26,6 @@ const props = defineProps() // Emits const emit = defineEmits<{ close: [] - sent: [] }>() const mailStore = useMailStore() @@ -222,7 +221,6 @@ const handleSend = async () => { text: editor.value?.getText() || '', }, }) - emit('sent') } catch (error) { console.error('[Mail][Composer] Failed to send message:', error) } diff --git a/src/components/MessageList.vue b/src/components/MessageList.vue index 9c88dc6..b3ecb98 100644 --- a/src/components/MessageList.vue +++ b/src/components/MessageList.vue @@ -23,72 +23,30 @@ const props = withDefaults(defineProps(), { // Emits const emit = defineEmits<{ open: [message: EntityObject] - toggleSelection: [message: EntityObject] - activateSelectionMode: [message: EntityObject] - toggleSelectAll: [value: boolean] - clearSelection: [] - moveSelection: [] - deleteSelection: [] + selectionMode: [message: EntityObject] + selectionToggleOne: [message: EntityObject] + selectionToggleAll: [value: boolean] + selectionClear: [] + selectionMove: [] + selectionDelete: [] }>() const longPressTimer = ref(null) const longPressActivated = ref(false) const suppressNextClick = ref(false) -const LONG_PRESS_MS = 450 - +const LONG_PRESS_MS = 400 const selectedIdSet = computed(() => new Set(props.selectionList)) - -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) - -const allCurrentMessagesSelected = computed(() => { - return currentMessages.value.length > 0 && currentMessages.value.every(message => isSelected(message)) -}) +const selectionCount = computed(() => props.selectionList.length ?? 0) // Sorted messages (newest first) const sortedMessages = computed(() => { - return [...currentMessages.value].sort((a, b) => { - const dateA = getMessageTimeValue(a) - const dateB = getMessageTimeValue(b) + return [...props.messages].sort((a, b) => { + const dateA = timeStamp(a) ?? 0 + const dateB = timeStamp(b) ?? 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 -}) - const isOpened = (message: EntityObject): boolean => { if (!props.selectedMessage) return false return (message.identifier === props.selectedMessage.identifier) @@ -98,8 +56,23 @@ const isSelected = (message: EntityObject): boolean => { return selectedIdSet.value.has(message.identifier) } +const timeStamp = (message: EntityObject): number | null => { + const timestamp = message.properties.received + || message.properties.sent + || message.modified + || message.created + || null + + if (!timestamp) { + return null + } + + const timeValue = new Date(timestamp).getTime() + return Number.isNaN(timeValue) ? null : timeValue +} + // Format date for display -const formatDate = (date: Date | string | null | undefined): string => { +const formatDate = (date: Date | string | number | null | undefined): string => { if (!date) return '' const messageDate = new Date(date) @@ -141,21 +114,19 @@ const formatDate = (date: Date | string | null | undefined): string => { }) } -// Truncate text -const truncate = (text: string | null | undefined, length: number = 100): string => { - if (!text) return '' - 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 handleSelectionToggleOne = (message: EntityObject) => { + emit('selectionToggleOne', message) } -const handleMessageMouseClick = (event: MouseEvent | KeyboardEvent, message: EntityObject) => { +const handleSelectionToggleAll = (value: boolean | null) => { + emit('selectionToggleAll', value === true) +} + +const handleMouseClick = (event: MouseEvent | KeyboardEvent, message: EntityObject) => { if (isSelectionControlClick(event)) { return } @@ -168,7 +139,7 @@ const handleMessageMouseClick = (event: MouseEvent | KeyboardEvent, message: Ent if (event.shiftKey && !props.selectionMode) { event.preventDefault() event.stopPropagation() - emit('activateSelectionMode', message) + emit('selectionMode', message) return } @@ -178,14 +149,14 @@ const handleMessageMouseClick = (event: MouseEvent | KeyboardEvent, message: Ent } if (props.selectionMode) { - emit('toggleSelection', message) + emit('selectionToggleOne', message) return } emit('open', message) } -const handleMessageMouseDown = (event: MouseEvent, message: EntityObject) => { +const handleMouseDown = (event: MouseEvent, message: EntityObject) => { if (isSelectionControlClick(event)) { return } @@ -197,14 +168,7 @@ const handleMessageMouseDown = (event: MouseEvent, message: EntityObject) => { event.preventDefault() event.stopPropagation() suppressNextClick.value = true - emit('activateSelectionMode', message) -} - -const clearLongPressTimer = () => { - if (longPressTimer.value !== null) { - window.clearTimeout(longPressTimer.value) - longPressTimer.value = null - } + emit('selectionMode', message) } const handleTouchStart = (message: EntityObject) => { @@ -213,9 +177,9 @@ const handleTouchStart = (message: EntityObject) => { longPressTimer.value = window.setTimeout(() => { if (!props.selectionMode) { - emit('activateSelectionMode', message) + emit('selectionMode', message) } else { - emit('toggleSelection', message) + emit('selectionToggleOne', message) } longPressActivated.value = true @@ -231,13 +195,16 @@ const handleTouchMove = () => { clearLongPressTimer() } +const clearLongPressTimer = () => { + if (longPressTimer.value !== null) { + window.clearTimeout(longPressTimer.value) + longPressTimer.value = null + } +} + onBeforeUnmount(() => { clearLongPressTimer() }) - -const handleSelectAllToggle = (value: boolean | null) => { - emit('toggleSelectAll', value === true) -}