import { InboxItem } from '../entities/InboxItem'; import { useStore } from '../store/useStore'; import { handleAuthResponse } from './authUtils'; import { getApiPath } from '../config/paths'; // API functions export const fetchInboxItems = async ( limit: number = 20, offset: number = 0 ): Promise<{ items: InboxItem[]; pagination: { total: number; limit: number; offset: number; hasMore: boolean; }; }> => { const params = new URLSearchParams({ limit: limit.toString(), offset: offset.toString(), }); const response = await fetch(getApiPath(`inbox?${params}`), { credentials: 'include', headers: { Accept: 'application/json', }, }); await handleAuthResponse(response, 'Failed to fetch inbox items.'); const result = await response.json(); // Handle backward compatibility - if it's an array, convert to new format if (Array.isArray(result)) { return { items: result, pagination: { total: result.length, limit: result.length, offset: 0, hasMore: false, }, }; } if (!result.items || !Array.isArray(result.items)) { throw new Error('Resulting inbox items are not in expected format.'); } return result; }; export const createInboxItem = async ( content: string, source?: string ): Promise => { const response = await fetch(getApiPath('inbox'), { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, body: JSON.stringify(source ? { content, source } : { content }), }); await handleAuthResponse(response, 'Failed to create inbox item.'); return await response.json(); }; export const updateInboxItem = async ( itemUid: string, content: string ): Promise => { const response = await fetch(getApiPath(`inbox/${itemUid}`), { method: 'PATCH', credentials: 'include', headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, body: JSON.stringify({ content }), }); await handleAuthResponse(response, 'Failed to update inbox item.'); return await response.json(); }; export const processInboxItem = async (itemUid: string): Promise => { const response = await fetch(getApiPath(`inbox/${itemUid}/process`), { method: 'PATCH', credentials: 'include', headers: { Accept: 'application/json', }, }); await handleAuthResponse(response, 'Failed to process inbox item.'); return await response.json(); }; export const deleteInboxItem = async (itemUid: string): Promise => { const response = await fetch(getApiPath(`inbox/${itemUid}`), { method: 'DELETE', credentials: 'include', headers: { Accept: 'application/json', }, }); await handleAuthResponse(response, 'Failed to delete inbox item.'); }; // Track last check time to detect new items // eslint-disable-next-line @typescript-eslint/no-unused-vars const lastCheckTimestamp = Date.now(); // Store-aware functions export const loadInboxItemsToStore = async ( isInitialLoad: boolean = false, requestedCount: number = 20 ): Promise => { const inboxStore = useStore.getState().inboxStore; // Only show loading for initial load, not for polling if (isInitialLoad && inboxStore.inboxItems.length === 0) { inboxStore.setLoading(true); inboxStore.resetPagination(); } try { // Load the requested number of items (for pagination preservation) const { items, pagination } = await fetchInboxItems(requestedCount, 0); // Check for new items since last check (only for non-initial loads) if (!isInitialLoad) { const currentItemUids = new Set( inboxStore.inboxItems.map((item) => item.uid).filter(Boolean) ); // New telegram items const newTelegramItems = items.filter( (item) => item.uid && !currentItemUids.has(item.uid) && item.source === 'telegram' ); // Only show notifications if we have detected changes if ( inboxStore.inboxItems.length > 0 && newTelegramItems.length > 0 ) { // Get some minimal info about the items for the notification const previewSource = newTelegramItems[0].title || newTelegramItems[0].content || ''; const notificationData = { count: newTelegramItems.length, firstItemContent: previewSource.substring(0, 30) + (previewSource.length > 30 ? '...' : ''), }; // Dispatch a custom event with the notification data window.dispatchEvent( new CustomEvent('inboxItemsUpdated', { detail: notificationData, }) ); } } // Update state inboxStore.setInboxItems(items); inboxStore.setPagination(pagination); inboxStore.setError(false); } catch (error) { console.error('Failed to load inbox items:', error); inboxStore.setError(true); } finally { // Only set loading to false if we were actually loading if (isInitialLoad) { inboxStore.setLoading(false); } } }; export const loadMoreInboxItemsToStore = async (): Promise => { const inboxStore = useStore.getState().inboxStore; if (!inboxStore.pagination.hasMore || inboxStore.isLoading) { return; } inboxStore.setLoading(true); try { const nextOffset = inboxStore.pagination.offset + inboxStore.pagination.limit; const { items, pagination } = await fetchInboxItems(20, nextOffset); // Append new items to existing ones inboxStore.appendInboxItems(items); inboxStore.setPagination(pagination); inboxStore.setError(false); } catch (error) { console.error('Failed to load more inbox items:', error); inboxStore.setError(true); } finally { inboxStore.setLoading(false); } }; export const createInboxItemWithStore = async ( content: string, source?: string ): Promise => { const inboxStore = useStore.getState().inboxStore; try { const newItem = await createInboxItem(content, source); inboxStore.addInboxItem(newItem); return newItem; } catch (error) { console.error('Failed to create inbox item:', error); throw error; } }; export const updateInboxItemWithStore = async ( itemUid: string, content: string ): Promise => { const inboxStore = useStore.getState().inboxStore; try { const updatedItem = await updateInboxItem(itemUid, content); inboxStore.updateInboxItem(updatedItem); return updatedItem; } catch (error) { console.error('Failed to update inbox item:', error); throw error; } }; export const processInboxItemWithStore = async ( itemUid: string ): Promise => { const inboxStore = useStore.getState().inboxStore; try { const processedItem = await processInboxItem(itemUid); inboxStore.removeInboxItemByUid(itemUid); return processedItem; } catch (error) { console.error('Failed to process inbox item:', error); throw error; } }; export const deleteInboxItemWithStore = async ( itemUid: string ): Promise => { const inboxStore = useStore.getState().inboxStore; try { await deleteInboxItem(itemUid); inboxStore.removeInboxItemByUid(itemUid); } catch (error) { console.error('Failed to delete inbox item:', error); throw error; } };