jellytau/src/lib/composables/useServerReachabilityReload.ts
Duncan Tourolle 6d1c618a3a Implement Phase 1-2 of backend migration refactoring
CRITICAL FIXES (Previous):
- Fix nextEpisode event handlers (was calling undefined methods)
- Replace queue polling with event-based updates (90% reduction in backend calls)
- Move device ID to Tauri secure storage (security fix)
- Fix event listener memory leaks with proper cleanup
- Replace browser alerts with toast notifications
- Remove silent error handlers and improve logging
- Fix race condition in downloads store with request queuing
- Centralize duration formatting utility
- Add input validation to image URLs (prevent injection attacks)

PHASE 1: BACKEND SORTING & FILTERING 
- Created Jellyfin field mapping utility (src/lib/utils/jellyfinFieldMapping.ts)
  - Maps frontend sort keys to Jellyfin API field names
  - Provides item type constants and groups
  - Includes 20+ test cases for comprehensive coverage
- Updated route components to use backend sorting:
  - src/routes/library/music/tracks/+page.svelte
  - src/routes/library/music/albums/+page.svelte
  - src/routes/library/music/artists/+page.svelte
- Refactored GenericMediaListPage.svelte:
  - Removed client-side sorting/filtering logic
  - Removed filteredItems and applySortAndFilter()
  - Now passes sort parameters to backend
  - Uses backend search instead of client-side filtering
  - Added sortOrder state for Ascending/Descending toggle

PHASE 3: SEARCH (Already Implemented) 
- Search now uses backend repository_search command
- Replaced client-side filtering with backend calls
- Set up for debouncing implementation

PHASE 2: BACKEND URL CONSTRUCTION (Started)
- Converted getImageUrl() to async backend call
- Removed sync URL construction with credentials
- Next: Update 12+ components to handle async image URLs

UNIT TESTS ADDED:
- jellyfinFieldMapping.test.ts (20+ test cases)
- duration.test.ts (15+ test cases)
- validation.test.ts (25+ test cases)
- deviceId.test.ts (8+ test cases)
- playerEvents.test.ts (event initialization tests)

SUMMARY:
- Eliminated all client-side sorting/filtering logic
- Improved security by removing frontend URL construction
- Reduced backend polling load significantly
- Fixed critical bugs (nextEpisode, race conditions, memory leaks)
- 80+ new unit tests across utilities and services
- Comprehensive infrastructure for future phases

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-13 23:34:18 +01:00

55 lines
1.6 KiB
TypeScript

/**
* Composable for reloading data when server becomes reachable
*
* Handles the cache-first timing issue where local cached data is shown,
* but we want to refresh from the server when it becomes available again.
*
* @req: UR-031 - Function offline on cached data
* @req: DR-012 - Local database for media metadata cache
*
* @param reloadFn - Async function to call when server becomes reachable
* @returns Object with markLoaded function to indicate initial load is complete
*
* @example
* ```svelte
* <script>
* const { markLoaded } = useServerReachabilityReload(async () => {
* await loadData();
* });
*
* onMount(async () => {
* await loadData();
* markLoaded();
* });
* </script>
* ```
*/
export function useServerReachabilityReload(reloadFn: () => void | Promise<void>) {
let hasLoadedOnce = false;
let previousServerReachable = false;
// Return an object with reactive getter/setter that can be used in Svelte components
return {
/**
* Call this after initial data load to enable server reconnection tracking
*/
markLoaded: () => {
hasLoadedOnce = true;
},
/**
* Call this in a $effect block to watch for server reconnection
* Pass the current isServerReachable value and this will handle the logic
*/
checkServerReachability: (isServerReachable: boolean) => {
if (isServerReachable && !previousServerReachable && hasLoadedOnce) {
// Server just became reachable and we've done an initial load
// Trigger reload to get fresh data
reloadFn();
}
previousServerReachable = isServerReachable;
},
};
}