b419af09eb
Signed-off-by: Sebastian <krupinski01@gmail.com>
86 lines
2.0 KiB
TypeScript
86 lines
2.0 KiB
TypeScript
/**
|
|
* Recipients Store
|
|
*/
|
|
|
|
import { ref } from 'vue'
|
|
import { defineStore } from 'pinia'
|
|
import { recipientService } from '../services/recipientService'
|
|
import type { MessageAddressInterface } from '@MailManager/types/message'
|
|
|
|
/** Minimum characters before a lookup fires. */
|
|
const MIN_QUERY_LENGTH = 3
|
|
|
|
/** Debounce window for keystroke-driven searches. */
|
|
const DEBOUNCE_MS = 250
|
|
|
|
export const useRecipientLookupStore = defineStore('mailRecipientsStore', () => {
|
|
const suggestions = ref<MessageAddressInterface[]>([])
|
|
const searching = ref(false)
|
|
|
|
let debounceTimer: ReturnType<typeof setTimeout> | null = null
|
|
// Monotonic token so out-of-order/stale responses are discarded.
|
|
let requestToken = 0
|
|
|
|
function cancelPending() {
|
|
if (debounceTimer) {
|
|
clearTimeout(debounceTimer)
|
|
debounceTimer = null
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear suggestions and cancel any in-flight lookup.
|
|
*/
|
|
function clear() {
|
|
cancelPending()
|
|
requestToken++
|
|
suggestions.value = []
|
|
searching.value = false
|
|
}
|
|
|
|
/**
|
|
* Debounced contact search. Queries shorter than MIN_QUERY_LENGTH clear the
|
|
* suggestion list without hitting the backend.
|
|
*/
|
|
function search(query: string) {
|
|
const trimmed = (query ?? '').trim()
|
|
cancelPending()
|
|
|
|
if (trimmed.length < MIN_QUERY_LENGTH) {
|
|
requestToken++
|
|
suggestions.value = []
|
|
searching.value = false
|
|
return
|
|
}
|
|
|
|
searching.value = true
|
|
const token = ++requestToken
|
|
|
|
debounceTimer = setTimeout(async () => {
|
|
try {
|
|
const matches = await recipientService.search(trimmed)
|
|
if (token !== requestToken) {
|
|
return
|
|
}
|
|
suggestions.value = matches
|
|
} catch (error: any) {
|
|
if (token === requestToken) {
|
|
suggestions.value = []
|
|
}
|
|
console.error('[Mail][Recipient Lookup] - Search failed:', error)
|
|
} finally {
|
|
if (token === requestToken) {
|
|
searching.value = false
|
|
}
|
|
}
|
|
}, DEBOUNCE_MS)
|
|
}
|
|
|
|
return {
|
|
suggestions,
|
|
searching,
|
|
search,
|
|
clear,
|
|
}
|
|
})
|