feat: implement patch and settings store

Signed-off-by: Sebastian <krupinski01@gmail.com>
This commit is contained in:
2026-05-19 22:27:51 -04:00
parent c3c41f7ba0
commit 8ba40a971e
9 changed files with 560 additions and 330 deletions

View File

@@ -0,0 +1,74 @@
import { computed } from 'vue'
import { defineStore } from 'pinia'
import { useUserStore } from '@KTXC'
const MESSAGE_READ_ENABLED_KEY = 'mail.behaviour.messageReadEnabled'
const MESSAGE_READ_DELAY_KEY = 'mail.behaviour.messageReadDelay'
const FOLDER_VIEW_MODE_KEY = 'mail.folderViewMode'
const DEFAULT_MESSAGE_READ_ENABLED = false
const DEFAULT_MESSAGE_READ_DELAY = 5
const DEFAULT_FOLDER_VIEW_MODE = 'tree'
export type FolderViewMode = 'tree' | 'page'
export const messageReadDelayOptions = [
{ value: 2, title: '2 seconds' },
{ value: 5, title: '5 seconds' },
{ value: 10, title: '10 seconds' },
{ value: 30, title: '30 seconds' },
]
export const folderViewModeOptions = [
{ value: 'tree', title: 'Tree' },
{ value: 'page', title: 'Page' },
]
function normalizeBoolean(value: unknown, fallback: boolean): boolean {
if (typeof value === 'boolean') {
return value
}
return fallback
}
function normalizePositiveNumber(value: unknown, fallback: number): number {
const normalized = Number(value)
return Number.isFinite(normalized) && normalized > 0 ? normalized : fallback
}
function normalizeFolderViewMode(value: unknown, fallback: FolderViewMode): FolderViewMode {
return value === 'tree' || value === 'page' ? value : fallback
}
export const useMailSettingsStore = defineStore('mailSettingsStore', () => {
const userStore = useUserStore()
const messageReadEnabled = computed({
get: () => normalizeBoolean(userStore.getSetting(MESSAGE_READ_ENABLED_KEY), DEFAULT_MESSAGE_READ_ENABLED),
set: (value: boolean) => userStore.setSetting(MESSAGE_READ_ENABLED_KEY, value),
})
const messageReadDelay = computed({
get: () => normalizePositiveNumber(userStore.getSetting(MESSAGE_READ_DELAY_KEY), DEFAULT_MESSAGE_READ_DELAY),
set: (value: number) => userStore.setSetting(
MESSAGE_READ_DELAY_KEY,
normalizePositiveNumber(value, DEFAULT_MESSAGE_READ_DELAY),
),
})
const folderViewMode = computed({
get: () => normalizeFolderViewMode(userStore.getSetting(FOLDER_VIEW_MODE_KEY), DEFAULT_FOLDER_VIEW_MODE),
set: (value: FolderViewMode) => userStore.setSetting(
FOLDER_VIEW_MODE_KEY,
normalizeFolderViewMode(value, DEFAULT_FOLDER_VIEW_MODE),
),
})
return {
folderViewMode,
messageReadEnabled,
messageReadDelay,
}
})

View File

@@ -78,9 +78,7 @@ export const useMailStore = defineStore('mailStore', () => {
await servicesStore.list()
const services = [...servicesStore.servicesEnabled]
services.forEach(service => {
void loadFoldersForService(service,{ selectInbox: true })
})
await Promise.all(services.map(service => loadFoldersForService(service)))
} catch (error) {
console.error('[Mail][Operations] Failed to initialize:', error)
} finally {
@@ -88,10 +86,7 @@ export const useMailStore = defineStore('mailStore', () => {
}
}
async function loadFoldersForService(
service: ServiceObject,
options: { selectInbox?: boolean } = {},
) {
async function loadFoldersForService(service: ServiceObject) {
if (service.identifier === null) {
return
@@ -102,24 +97,10 @@ export const useMailStore = defineStore('mailStore', () => {
try {
// retrieve folders for service
const collections = await collectionsStore.collectionsForService(service.provider, service.identifier, true)
await collectionsStore.collectionsForService(service.provider, service.identifier, true)
_setServiceFolderLoaded(service.provider, service.identifier, true)
if (options.selectInbox && !selectedFolder.value) {
const inbox = Object.values(collections).find(
folder =>
folder.provider === service.provider &&
String(folder.service) === String(service.identifier) &&
(folder.properties.role === 'inbox' ||
String(folder.identifier).toLowerCase() === 'inbox'),
)
if (inbox) {
await selectFolder(inbox)
}
}
_updateSyncSources()
} catch (error) {
const message = error instanceof Error ? error.message : 'Failed to load folders'
@@ -323,41 +304,25 @@ export const useMailStore = defineStore('mailStore', () => {
return service
}
async function selectFolder(folder: CollectionObject) {
async function selectFolder(folder: CollectionObject | null) {
selectedFolder.value = folder
selectedMessage.value = null
try {
await entitiesStore.list([folder.identifier])
} catch (error) {
console.error('[Mail][Operations] Failed to load messages:', error)
if (folder) {
try {
await entitiesStore.list([folder.identifier])
} catch (error) {
console.error('[Mail][Operations] Failed to load messages:', error)
}
}
_updateSyncSources()
}
function clearSelectedFolder() {
selectedFolder.value = null
selectedMessage.value = null
_updateSyncSources()
}
function selectMessage(entity: EntityObject) {
function selectMessage(entity: EntityObject | null) {
selectedMessage.value = entity
}
function clearSelectedMessage() {
selectedMessage.value = null
}
async function reloadSelectedFolder() {
// Reload the current folder so the sent message appears in Sent
if (selectedFolder.value) {
await selectFolder(selectedFolder.value)
}
}
async function saveComposerDraft(folder: CollectionObject, message: ComposerMessageInput) {
composerSaving.value = true
@@ -380,6 +345,24 @@ export const useMailStore = defineStore('mailStore', () => {
}
}
function findFoldersByRole(role: string): CollectionObject[] {
const normalizedRole = role.toLowerCase()
return servicesStore.servicesEnabled.flatMap(service => {
if (service.identifier === null) {
return []
}
return collectionsStore.collectionsForService(service.provider, service.identifier).filter(
folder =>
folder.provider === service.provider &&
String(folder.service) === String(service.identifier) &&
(folder.properties.role === normalizedRole ||
String(folder.identifier).toLowerCase() === normalizedRole),
)
})
}
async function sendComposerMessage(message: ComposerMessageInput) {
composerSending.value = true
@@ -492,7 +475,7 @@ export const useMailStore = defineStore('mailStore', () => {
const deletedFolder = await collectionsStore.delete(folder.identifier)
if (_sameCollection(selectedFolder.value, folder)) {
clearSelectedFolder()
await selectFolder(null)
}
notify(
@@ -503,6 +486,81 @@ export const useMailStore = defineStore('mailStore', () => {
return deletedFolder
}
async function deleteMessages(entityIdentifiers: EntityIdentifier[]) {
if (entityIdentifiers.length === 0) {
return
}
loading.value = true
try {
const { successes, failures } = await entitiesStore.delete(entityIdentifiers)
if (failures.length === 0) {
notify(
successes.length === 1 ? 'Message deleted' : `${successes.length} messages deleted`,
'success',
)
}
if (failures.length > 0) {
notify(
successes.length === 0
? `Delete failed for ${failures.length === 1 ? '1 message' : `${failures.length} messages`}`
: `Deleted ${successes.length} ${successes.length === 1 ? 'message' : 'messages'}. ${failures.length} failed.`,
successes.length === 0 ? 'error' : 'warning',
)
}
} catch (error) {
const messageText = error instanceof Error ? error.message : 'Failed to delete messages'
console.error('[Mail][Operations] Failed to delete messages:', error)
notify(messageText, 'error')
throw error
} finally {
loading.value = false
}
}
async function flagMessages(entityIdentifiers: EntityIdentifier[], flags: Partial<MessageInterface['flags']>, options: { notify?: boolean } = {}) {
if (entityIdentifiers.length === 0) {
return
}
const shouldNotify = options.notify ?? true
loading.value = true
try {
const patch = entitiesStore.fresh().properties
patch.flags = flags
const { successes, failures } = await entitiesStore.patch(patch, entityIdentifiers)
if (shouldNotify && successes.length > 0) {
notify(
successes.length === 1 ? 'Message updated' : `${successes.length} messages updated`,
'success',
)
}
if (shouldNotify && failures.length > 0) {
notify(
successes.length === 0
? `Update failed for ${failures.length === 1 ? '1 message' : `${failures.length} messages`}`
: `Updated ${successes.length} ${successes.length === 1 ? 'message' : 'messages'}. ${failures.length} failed.`,
successes.length === 0 ? 'error' : 'warning',
)
}
} catch (error) {
const messageText = error instanceof Error ? error.message : 'Failed to update messages'
console.error('[Mail][Operations] Failed to update messages:', error)
notify(messageText, 'error')
throw error
} finally {
loading.value = false
}
}
async function moveMessages(target: CollectionObject, entityIdentifiers: EntityIdentifier[]) {
const { movableIdentifiers, sourceCollections } = entityIdentifiers.reduce(
(accumulator, identifier) => {
@@ -575,41 +633,6 @@ export const useMailStore = defineStore('mailStore', () => {
}
}
async function deleteMessages(entityIdentifiers: EntityIdentifier[]) {
if (entityIdentifiers.length === 0) {
return
}
loading.value = true
try {
const { successes, failures } = await entitiesStore.delete(entityIdentifiers)
if (failures.length === 0) {
notify(
successes.length === 1 ? 'Message deleted' : `${successes.length} messages deleted`,
'success',
)
}
if (failures.length > 0) {
notify(
successes.length === 0
? `Delete failed for ${failures.length === 1 ? '1 message' : `${failures.length} messages`}`
: `Deleted ${successes.length} ${successes.length === 1 ? 'message' : 'messages'}. ${failures.length} failed.`,
successes.length === 0 ? 'error' : 'warning',
)
}
} catch (error) {
const messageText = error instanceof Error ? error.message : 'Failed to delete messages'
console.error('[Mail][Operations] Failed to delete messages:', error)
notify(messageText, 'error')
throw error
} finally {
loading.value = false
}
}
function notify(message: string, color: 'success' | 'error' | 'info' | 'warning' = 'success') {
showSnackbar({ message, color })
}
@@ -625,7 +648,6 @@ export const useMailStore = defineStore('mailStore', () => {
// State
loading,
selectedFolder,
selectedMessage,
composerSaving,
composerSending,
@@ -641,14 +663,12 @@ export const useMailStore = defineStore('mailStore', () => {
// Actions
retrieveService,
selectFolder,
clearSelectedFolder,
selectMessage,
clearSelectedMessage,
createFolder,
reloadSelectedFolder,
saveComposerDraft,
sendComposerMessage,
resetComposerState,
flagMessages,
deleteMessages,
deleteFolder,
moveMessages,
@@ -658,6 +678,7 @@ export const useMailStore = defineStore('mailStore', () => {
isServiceFolderLoading,
hasServiceFoldersLoaded,
getServiceFolderError,
findFoldersByRole,
loadFoldersForService,
initialize,
}

View File

@@ -2,16 +2,20 @@ import { computed, ref, shallowRef, watch } from 'vue'
import { defineStore } from 'pinia'
import { useCollectionsStore } from '@MailManager/stores/collectionsStore'
import { useMailStore } from '@/stores/mailStore'
import { useMailSettingsStore } from '@/stores/mailSettingsStore'
import type { ServiceIdentifier, EntityIdentifier } from '@MailManager/types/common'
import type { EntityObject, ServiceObject } from '@MailManager/models'
import { EntityObject, type ServiceObject } from '@MailManager/models'
import type { CollectionObject } from '@MailManager/models/collection'
export const useMailUiStore = defineStore('mailUiStore', () => {
const collectionsStore = useCollectionsStore()
const mailStore = useMailStore()
const mailSettingsStore = useMailSettingsStore()
const sidebarVisible = ref(true)
const settingsDialogVisible = ref(false)
const selectedFolder = shallowRef<CollectionObject | null>(null)
const selectedMessage = shallowRef<EntityObject | null>(null)
const composeMode = ref<'new' | 'reply' | 'forward'>('new')
const composeSource = shallowRef<EntityObject | null>(null)
const composeVisible = ref(false)
@@ -38,6 +42,8 @@ export const useMailUiStore = defineStore('mailUiStore', () => {
const deleteFolderDialogFolder = shallowRef<CollectionObject | null>(null)
const deleteFolderDialogLoading = ref(false)
const deleteFolderDialogError = ref('')
const messageReadIdentifier = ref<EntityIdentifier | null>(null)
const messageReadTimer = ref<ReturnType<typeof setTimeout> | null>(null)
const createFolderDialogParentLabel = computed(() => {
return createFolderDialogParent.value?.properties.label || 'Root'
@@ -86,20 +92,14 @@ export const useMailUiStore = defineStore('mailUiStore', () => {
return Array.from(invalidKeys)
})
watch(
() => mailStore.selectedFolder,
() => {
closeCompose()
deactivateSelectionMode()
},
)
watch(
() => mailStore.selectedMessage,
selectedMessage => {
if (selectedMessage) {
message => {
if (message) {
closeCompose()
}
selectMessage(message)
},
)
@@ -110,6 +110,260 @@ export const useMailUiStore = defineStore('mailUiStore', () => {
},
)
function sidebarToggle() {
sidebarVisible.value = !sidebarVisible.value
}
function sidebarHide() {
sidebarVisible.value = false
}
function settingsOpen() {
settingsDialogVisible.value = true
}
function settingsClose() {
settingsDialogVisible.value = false
}
function _sameCollection(left: CollectionObject | null | undefined, right: CollectionObject | null | undefined): boolean {
if (!left || !right) {
return false
}
return left.provider === right.provider &&
String(left.service) === String(right.service) &&
String(left.identifier) === String(right.identifier)
}
async function initialize() {
await mailStore.initialize()
if (!selectedFolder.value) {
const inbox = mailStore.findFoldersByRole('inbox')[0] ?? null
if (inbox) {
await selectFolder(inbox)
}
}
}
async function selectFolder(folder: CollectionObject | null) {
closeCompose()
messageSelectionModeDeactivate()
clearMessageReadTimer()
selectedFolder.value = folder
await mailStore.selectFolder(folder)
}
async function selectMessage(message: EntityObject | null) {
closeCompose()
messageSelectionModeDeactivate()
createMessageReadTimer(message)
// mailStore.selectMessage(message)
}
function createMessageReadTimer(entity: EntityObject | null) {
clearMessageReadTimer()
if (!entity) {
return
}
if (entity.properties.isRead || !mailSettingsStore.messageReadEnabled) {
return
}
const delayMilliseconds = mailSettingsStore.messageReadDelay * 1000
if (delayMilliseconds <= 0) {
return
}
messageReadIdentifier.value = entity.identifier
messageReadTimer.value = setTimeout(() => {
void completeMessageRead(entity.identifier)
}, delayMilliseconds)
}
function clearMessageReadTimer() {
if (messageReadTimer.value !== null) {
clearTimeout(messageReadTimer.value)
}
messageReadTimer.value = null
messageReadIdentifier.value = null
}
async function completeMessageRead(identifier: EntityIdentifier) {
try {
if (selectedMessage.value && selectedMessage.value.identifier === identifier && selectedMessage.value.properties.isRead === false) {
await mailStore.flagMessages([selectedMessage.value.identifier], { read: true }, { notify: false })
}
} catch (error) {
console.error('[Mail][UI] Failed to auto-mark message as read:', error)
} finally {
clearMessageReadTimer()
}
}
function openCreateFolderDialog(service: ServiceObject, parentFolder: CollectionObject | null = null) {
createFolderDialogService.value = service
createFolderDialogParent.value = parentFolder
createFolderDialogError.value = ''
createFolderDialogLoading.value = false
createFolderDialogVisible.value = true
}
function closeCreateFolderDialog() {
createFolderDialogVisible.value = false
createFolderDialogService.value = null
createFolderDialogParent.value = null
createFolderDialogError.value = ''
createFolderDialogLoading.value = false
}
async function confirmCreateFolder(label: string) {
const service = createFolderDialogService.value
if (!service) {
return null
}
createFolderDialogLoading.value = true
createFolderDialogError.value = ''
try {
const folder = await mailStore.createFolder(service, label, createFolderDialogParent.value)
closeCreateFolderDialog()
return folder
} catch (error) {
createFolderDialogError.value = error instanceof Error ? error.message : 'Failed to create folder. Please try again.'
throw error
} finally {
createFolderDialogLoading.value = false
}
}
async function openRenameFolderDialog(target: CollectionObject) {
const service = await mailStore.retrieveService(target.service)
renameFolderDialogService.value = service
renameFolderDialogFolder.value = target
renameFolderDialogError.value = ''
renameFolderDialogLoading.value = false
renameFolderDialogVisible.value = true
}
function closeRenameFolderDialog() {
renameFolderDialogVisible.value = false
renameFolderDialogService.value = null
renameFolderDialogFolder.value = null
renameFolderDialogError.value = ''
renameFolderDialogLoading.value = false
}
async function confirmRenameFolder(label: string) {
const folder = renameFolderDialogFolder.value
if (!folder) {
return null
}
renameFolderDialogLoading.value = true
renameFolderDialogError.value = ''
try {
const updatedFolder = await mailStore.renameFolder(folder, label)
if (_sameCollection(selectedFolder.value, folder)) {
selectedFolder.value = updatedFolder
}
closeRenameFolderDialog()
return updatedFolder
} catch (error) {
renameFolderDialogError.value = error instanceof Error ? error.message : 'Failed to rename folder. Please try again.'
throw error
} finally {
renameFolderDialogLoading.value = false
}
}
async function openMoveFolderDialog(source: CollectionObject) {
const service = await mailStore.retrieveService(source.service)
moveFolderDialogService.value = service
moveFolderDialogSource.value = source
moveFolderDialogVisible.value = true
}
function closeMoveFolderDialog() {
moveFolderDialogVisible.value = false
moveFolderDialogService.value = null
moveFolderDialogSource.value = null
}
async function confirmMoveFolder(target: CollectionObject) {
const source = moveFolderDialogSource.value
if (!source) {
return null
}
const movedFolder = await mailStore.moveFolder(source, target)
if (_sameCollection(selectedFolder.value, source)) {
selectedFolder.value = movedFolder
}
closeMoveFolderDialog()
return movedFolder
}
async function openDeleteFolderDialog(target: CollectionObject) {
const service = await mailStore.retrieveService(target.service)
deleteFolderDialogService.value = service
deleteFolderDialogFolder.value = target
deleteFolderDialogError.value = ''
deleteFolderDialogLoading.value = false
deleteFolderDialogVisible.value = true
}
function closeDeleteFolderDialog() {
deleteFolderDialogVisible.value = false
deleteFolderDialogService.value = null
deleteFolderDialogFolder.value = null
deleteFolderDialogError.value = ''
deleteFolderDialogLoading.value = false
}
async function confirmDeleteFolder() {
const folder = deleteFolderDialogFolder.value
if (!folder) {
return null
}
deleteFolderDialogLoading.value = true
deleteFolderDialogError.value = ''
try {
const deleted = await mailStore.deleteFolder(folder)
if (_sameCollection(selectedFolder.value, folder)) {
selectFolder(null)
}
closeDeleteFolderDialog()
return deleted
} catch (error) {
deleteFolderDialogError.value = error instanceof Error ? error.message : 'Failed to delete folder. Please try again.'
throw error
} finally {
deleteFolderDialogLoading.value = false
}
}
function validateFolderNameBase(service: ServiceObject, name: string): string[] {
const errors: string[] = []
@@ -196,7 +450,7 @@ export const useMailUiStore = defineStore('mailUiStore', () => {
}
function openCompose(source?: EntityObject, mode: 'reply' | 'forward' = 'reply') {
mailStore.clearSelectedMessage()
mailStore.selectMessage(null)
composeSource.value = source ?? null
composeMode.value = mode
composeVisible.value = true
@@ -254,7 +508,7 @@ export const useMailUiStore = defineStore('mailUiStore', () => {
}
function messageSelectionReconcile() {
if (!mailStore.selectedFolder) {
if (!selectedFolder.value) {
messageSelectionClear()
return
}
@@ -271,22 +525,6 @@ export const useMailUiStore = defineStore('mailUiStore', () => {
}
}
function toggleSidebar() {
sidebarVisible.value = !sidebarVisible.value
}
function closeSidebar() {
sidebarVisible.value = false
}
function openSettings() {
settingsDialogVisible.value = true
}
function closeSettings() {
settingsDialogVisible.value = false
}
async function openMoveMessagesDialog(entities?: EntityObject | EntityObject[]) {
let moveMessagesServiceIdentifier = null as ServiceIdentifier | null
@@ -302,10 +540,10 @@ export const useMailUiStore = defineStore('mailUiStore', () => {
}
} else {
moveMessagesDialogCandidates.value = [...selectionList.value]
moveMessagesServiceIdentifier = mailStore.selectedFolder?.service as ServiceIdentifier || null
moveMessagesServiceIdentifier = selectedFolder.value?.service as ServiceIdentifier || null
}
moveMessagesDialogService.value = await mailStore.retrieveService(moveMessagesServiceIdentifier);
moveMessagesDialogService.value = await mailStore.retrieveService(moveMessagesServiceIdentifier)
moveMessagesDialogVisible.value = true
}
@@ -323,153 +561,19 @@ export const useMailUiStore = defineStore('mailUiStore', () => {
async function deleteSelectedMessages() {
await mailStore.deleteMessages([...selectionList.value])
deactivateSelectionMode()
messageSelectionModeDeactivate()
}
function openCreateFolderDialog(service: ServiceObject, parentFolder: CollectionObject | null = null) {
createFolderDialogService.value = service
createFolderDialogParent.value = parentFolder
createFolderDialogError.value = ''
createFolderDialogLoading.value = false
createFolderDialogVisible.value = true
}
function closeCreateFolderDialog() {
createFolderDialogVisible.value = false
createFolderDialogService.value = null
createFolderDialogParent.value = null
createFolderDialogError.value = ''
createFolderDialogLoading.value = false
}
async function confirmCreateFolder(label: string) {
const service = createFolderDialogService.value
if (!service) {
return null
}
createFolderDialogLoading.value = true
createFolderDialogError.value = ''
try {
const folder = await mailStore.createFolder(service, label, createFolderDialogParent.value)
closeCreateFolderDialog()
return folder
} catch (error) {
createFolderDialogError.value = error instanceof Error ? error.message : 'Failed to create folder. Please try again.'
throw error
} finally {
createFolderDialogLoading.value = false
}
}
async function openRenameFolderDialog(target: CollectionObject) {
const service = await mailStore.retrieveService(target.service)
renameFolderDialogService.value = service
renameFolderDialogFolder.value = target
renameFolderDialogError.value = ''
renameFolderDialogLoading.value = false
renameFolderDialogVisible.value = true
}
function closeRenameFolderDialog() {
renameFolderDialogVisible.value = false
renameFolderDialogService.value = null
renameFolderDialogFolder.value = null
renameFolderDialogError.value = ''
renameFolderDialogLoading.value = false
}
async function confirmRenameFolder(label: string) {
const folder = renameFolderDialogFolder.value
if (!folder) {
return null
}
renameFolderDialogLoading.value = true
renameFolderDialogError.value = ''
try {
const updatedFolder = await mailStore.renameFolder(folder, label)
closeRenameFolderDialog()
return updatedFolder
} catch (error) {
renameFolderDialogError.value = error instanceof Error ? error.message : 'Failed to rename folder. Please try again.'
throw error
} finally {
renameFolderDialogLoading.value = false
}
}
async function openMoveFolderDialog(source: CollectionObject) {
const service = await mailStore.retrieveService(source.service)
moveFolderDialogService.value = service
moveFolderDialogSource.value = source
moveFolderDialogVisible.value = true
}
function closeMoveFolderDialog() {
moveFolderDialogVisible.value = false
moveFolderDialogService.value = null
moveFolderDialogSource.value = null
}
async function confirmMoveFolder(target: CollectionObject) {
const source = moveFolderDialogSource.value
if (!source) {
return null
}
const movedFolder = await mailStore.moveFolder(source, target)
closeMoveFolderDialog()
return movedFolder
}
async function openDeleteFolderDialog(target: CollectionObject) {
const service = await mailStore.retrieveService(target.service)
deleteFolderDialogService.value = service
deleteFolderDialogFolder.value = target
deleteFolderDialogError.value = ''
deleteFolderDialogLoading.value = false
deleteFolderDialogVisible.value = true
}
function closeDeleteFolderDialog() {
deleteFolderDialogVisible.value = false
deleteFolderDialogService.value = null
deleteFolderDialogFolder.value = null
deleteFolderDialogError.value = ''
deleteFolderDialogLoading.value = false
}
async function confirmDeleteFolder() {
const folder = deleteFolderDialogFolder.value
if (!folder) {
return null
}
deleteFolderDialogLoading.value = true
deleteFolderDialogError.value = ''
try {
const deleted = await mailStore.deleteFolder(folder)
closeDeleteFolderDialog()
return deleted
} catch (error) {
deleteFolderDialogError.value = error instanceof Error ? error.message : 'Failed to delete folder. Please try again.'
throw error
} finally {
deleteFolderDialogLoading.value = false
}
async function flagSelectedMessages(flag: string, value: boolean) {
await mailStore.flagMessages([...selectionList.value], { [flag]: value })
messageSelectionModeDeactivate()
}
return {
sidebarVisible,
settingsDialogVisible,
selectedFolder,
selectedMessage,
composeMode,
composeSource,
composeVisible,
@@ -499,13 +603,14 @@ export const useMailUiStore = defineStore('mailUiStore', () => {
deleteFolderDialogFolder,
deleteFolderDialogLoading,
deleteFolderDialogError,
toggleSidebar,
closeSidebar,
openSettings,
closeSettings,
sidebarToggle,
sidebarHide,
settingsOpen,
settingsClose,
initialize,
selectFolder,
openCompose,
closeCompose,
afterSent,
messageSelectionModeActivate,
messageSelectionModeDeactivate,
messageSelectionToggleOne,
@@ -529,5 +634,6 @@ export const useMailUiStore = defineStore('mailUiStore', () => {
openDeleteFolderDialog,
closeDeleteFolderDialog,
confirmDeleteFolder,
flagSelectedMessages,
}
})