refactor: use module store
Signed-off-by: Sebastian <krupinski01@gmail.com>
This commit is contained in:
@@ -1,22 +1,20 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, watch } from 'vue'
|
||||
import { computed, onMounted } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useDisplay } from 'vuetify'
|
||||
import { useModuleStore } from '@KTXC'
|
||||
import { useCollectionsStore } from '@MailManager/stores/collectionsStore'
|
||||
import { useEntitiesStore } from '@MailManager/stores/entitiesStore'
|
||||
import { useServicesStore } from '@MailManager/stores/servicesStore'
|
||||
import { useMailSync } from '@MailManager/composables/useMailSync'
|
||||
import type { CollectionObject } from '@MailManager/models/collection'
|
||||
import type { EntityInterface } from '@MailManager/types/entity'
|
||||
import type { MessageInterface } from '@MailManager/types/message'
|
||||
import { useMailStore } from '@/stores/mailStore'
|
||||
import FolderTree from '@/components/FolderTree.vue'
|
||||
import MessageList from '@/components/MessageList.vue'
|
||||
import MessageReader from '@/components/MessageReader.vue'
|
||||
import MessageComposer from '@/components/MessageComposer.vue'
|
||||
import SettingsDialog from '@/components/settings/SettingsDialog.vue'
|
||||
import type { EntityInterface } from '@MailManager/types/entity'
|
||||
import type { MessageInterface } from '@MailManager/types/message'
|
||||
|
||||
// Vuetify display for responsive behavior
|
||||
const display = useDisplay()
|
||||
const isMobile = computed(() => display.mdAndDown.value)
|
||||
|
||||
// Check if mail manager is available
|
||||
const moduleStore = useModuleStore()
|
||||
@@ -24,194 +22,59 @@ const isMailManagerAvailable = computed(() => {
|
||||
return moduleStore.has('mail_manager') || moduleStore.has('MailManager')
|
||||
})
|
||||
|
||||
// Snackbar state for notifications
|
||||
const snackbarVisible = ref(false)
|
||||
const snackbarMessage = ref('')
|
||||
const snackbarColor = ref('success')
|
||||
// Mail store — single source of truth for all mail UI state
|
||||
const mailStore = useMailStore()
|
||||
|
||||
// Stores
|
||||
const collectionsStore = useCollectionsStore()
|
||||
const entitiesStore = useEntitiesStore()
|
||||
const servicesStore = useServicesStore()
|
||||
// storeToRefs preserves reactivity for state and computed properties
|
||||
const {
|
||||
sidebarVisible,
|
||||
settingsDialogVisible,
|
||||
loading,
|
||||
selectedFolder,
|
||||
selectedMessage,
|
||||
composeMode,
|
||||
composeReplyTo,
|
||||
snackbarVisible,
|
||||
snackbarMessage,
|
||||
snackbarColor,
|
||||
currentMessages,
|
||||
} = storeToRefs(mailStore)
|
||||
|
||||
// Background mail sync
|
||||
const mailSync = useMailSync({
|
||||
interval: 30000, // Check every 30 seconds
|
||||
autoStart: false, // We'll start it manually after initialization
|
||||
fetchDetails: true, // Auto-fetch full message details for new/modified messages
|
||||
})
|
||||
|
||||
// UI state
|
||||
const sidebarVisible = ref(true)
|
||||
const selectedFolder = ref<CollectionObject | null>(null)
|
||||
const selectedMessage = ref<EntityInterface<MessageInterface> | null>(null)
|
||||
const composeMode = ref(false)
|
||||
const composeReplyTo = ref<EntityInterface<MessageInterface> | null>(null)
|
||||
const settingsDialogVisible = ref(false)
|
||||
|
||||
// Loading state
|
||||
const loading = ref(false)
|
||||
|
||||
// Computed
|
||||
const isMobile = computed(() => display.mdAndDown.value)
|
||||
// Complex store/composable objects accessed directly (not simple refs)
|
||||
const { mailSync, entitiesStore } = mailStore
|
||||
|
||||
// Initialize
|
||||
onMounted(async () => {
|
||||
if (!isMailManagerAvailable.value) return
|
||||
|
||||
loading.value = true
|
||||
try {
|
||||
// Load services (accounts)
|
||||
await servicesStore.list()
|
||||
|
||||
// Load collections (folders)
|
||||
await collectionsStore.list()
|
||||
|
||||
// Select inbox by default if available
|
||||
const inbox = collectionsStore.collections.find(c => c.properties.role === 'inbox')
|
||||
if (inbox) {
|
||||
handleFolderSelect(inbox)
|
||||
}
|
||||
|
||||
// Start background sync after initialization
|
||||
mailSync.start()
|
||||
} catch (error) {
|
||||
console.error('[Mail] Failed to initialize:', error)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
await mailStore.initialize()
|
||||
})
|
||||
|
||||
// Watch for folder and service changes to update sync sources
|
||||
watch(
|
||||
[selectedFolder, () => servicesStore.services],
|
||||
() => {
|
||||
if (!isMailManagerAvailable.value) return
|
||||
// Handlers — thin wrappers that delegate to the store
|
||||
const handleFolderSelect = (folder: Parameters<typeof mailStore.selectFolder>[0]) =>
|
||||
mailStore.selectFolder(folder)
|
||||
|
||||
mailSync.clearSources()
|
||||
const handleMessageSelect = (message: EntityInterface<MessageInterface>) =>
|
||||
mailStore.selectMessage(message, isMobile.value)
|
||||
|
||||
// Add currently selected folder to sync
|
||||
if (selectedFolder.value) {
|
||||
mailSync.addSource({
|
||||
provider: selectedFolder.value.provider,
|
||||
service: selectedFolder.value.service,
|
||||
collections: [selectedFolder.value.identifier],
|
||||
})
|
||||
}
|
||||
const handleCompose = (replyTo?: EntityInterface<MessageInterface>) =>
|
||||
mailStore.openCompose(replyTo)
|
||||
|
||||
// Add inbox for each service to get notifications
|
||||
servicesStore.services.forEach(service => {
|
||||
// Find inbox collection for this service
|
||||
const inboxes = collectionsStore.collections.filter(
|
||||
c => c.service === service.identifier &&
|
||||
(c.properties.role === 'inbox' ||
|
||||
String(c.identifier).toLowerCase() === 'inbox')
|
||||
)
|
||||
const handleComposeClose = () => mailStore.closeCompose()
|
||||
|
||||
if (inboxes.length > 0) {
|
||||
mailSync.addSource({
|
||||
provider: service.provider,
|
||||
service: service.identifier as string | number,
|
||||
collections: inboxes.map(inbox => inbox.identifier),
|
||||
})
|
||||
}
|
||||
})
|
||||
const handleComposeSent = () => mailStore.afterSent()
|
||||
|
||||
// Restart sync with updated sources
|
||||
if (mailSync.sources.value.length > 0 && !mailSync.isRunning.value) {
|
||||
mailSync.start()
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
const handleReply = (message: EntityInterface<MessageInterface>) =>
|
||||
mailStore.openCompose(message)
|
||||
|
||||
// Handlers
|
||||
const handleFolderSelect = async (folder: CollectionObject) => {
|
||||
selectedFolder.value = folder
|
||||
selectedMessage.value = null
|
||||
composeMode.value = false
|
||||
|
||||
// Load messages for this folder
|
||||
try {
|
||||
await entitiesStore.list({
|
||||
[folder.provider]: {
|
||||
[folder.service]: {
|
||||
[folder.identifier]: true
|
||||
}
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('[Mail] Failed to load messages:', error)
|
||||
}
|
||||
}
|
||||
const handleDelete = (message: EntityInterface<MessageInterface>) =>
|
||||
mailStore.deleteMessage(message)
|
||||
|
||||
const handleMessageSelect = (message: EntityInterface<MessageInterface>) => {
|
||||
selectedMessage.value = message
|
||||
composeMode.value = false
|
||||
|
||||
// Close sidebar on mobile after selection
|
||||
if (isMobile.value) {
|
||||
sidebarVisible.value = false
|
||||
}
|
||||
}
|
||||
const toggleSidebar = () => mailStore.toggleSidebar()
|
||||
|
||||
const handleCompose = (replyTo?: EntityInterface<MessageInterface>) => {
|
||||
composeMode.value = true
|
||||
composeReplyTo.value = replyTo || null
|
||||
selectedMessage.value = null
|
||||
}
|
||||
const handleSettingsOpen = () => mailStore.openSettings()
|
||||
|
||||
const handleComposeClose = () => {
|
||||
composeMode.value = false
|
||||
composeReplyTo.value = null
|
||||
}
|
||||
|
||||
const handleComposeSent = () => {
|
||||
composeMode.value = false
|
||||
composeReplyTo.value = null
|
||||
|
||||
// Reload current folder to show sent message in Sent folder
|
||||
if (selectedFolder.value) {
|
||||
handleFolderSelect(selectedFolder.value)
|
||||
}
|
||||
}
|
||||
|
||||
const handleReply = (message: EntityInterface<MessageInterface>) => {
|
||||
handleCompose(message)
|
||||
}
|
||||
|
||||
const handleDelete = async (message: EntityInterface<MessageInterface>) => {
|
||||
// TODO: Implement delete functionality
|
||||
console.log('[Mail] Delete message:', message.identifier)
|
||||
}
|
||||
|
||||
const toggleSidebar = () => {
|
||||
sidebarVisible.value = !sidebarVisible.value
|
||||
}
|
||||
|
||||
const handleSettingsOpen = () => {
|
||||
settingsDialogVisible.value = true
|
||||
}
|
||||
|
||||
const handleFolderCreated = (folder: CollectionObject) => {
|
||||
snackbarMessage.value = `Folder "${folder.properties.label}" created successfully`
|
||||
snackbarColor.value = 'success'
|
||||
snackbarVisible.value = true
|
||||
|
||||
// Reload collections to ensure UI is in sync
|
||||
collectionsStore.list()
|
||||
}
|
||||
|
||||
// Messages for current folder
|
||||
const currentMessages = computed(() => {
|
||||
if (!selectedFolder.value) return []
|
||||
|
||||
return entitiesStore.entitiesForCollection(
|
||||
selectedFolder.value.provider,
|
||||
selectedFolder.value.service,
|
||||
selectedFolder.value.identifier
|
||||
)
|
||||
})
|
||||
const handleFolderCreated = (folder: Parameters<typeof mailStore.onFolderCreated>[0]) =>
|
||||
mailStore.onFolderCreated(folder)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
Reference in New Issue
Block a user