feat: implement patch and settings store
Signed-off-by: Sebastian <krupinski01@gmail.com>
This commit is contained in:
74
src/stores/mailSettingsStore.ts
Normal file
74
src/stores/mailSettingsStore.ts
Normal 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,
|
||||
}
|
||||
})
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user