124 lines
4.3 KiB
TypeScript
124 lines
4.3 KiB
TypeScript
import { useCallback } from 'react';
|
|
import { useAppSelector } from '../redux';
|
|
import { selectControllerName, selectCurrentSinger, selectQueueObject } from '../redux';
|
|
import { queueService, favoritesService } from '../firebase/services';
|
|
import { ref, get } from 'firebase/database';
|
|
import { database } from '../firebase/config';
|
|
import { debugLog } from '../utils/logger';
|
|
import { useErrorHandler } from './index';
|
|
import type { Song, QueueItem } from '../types';
|
|
|
|
export const useSongOperations = () => {
|
|
const controllerName = useAppSelector(selectControllerName);
|
|
const currentSinger = useAppSelector(selectCurrentSinger);
|
|
const currentQueue = useAppSelector(selectQueueObject);
|
|
const { handleFirebaseError } = useErrorHandler({ context: 'useSongOperations' });
|
|
|
|
const addToQueue = useCallback(async (song: Song) => {
|
|
if (!controllerName || !currentSinger) {
|
|
throw new Error('Controller name or singer not available');
|
|
}
|
|
|
|
try {
|
|
// Calculate the next order by finding the highest order value and adding 1
|
|
const queueItems = Object.values(currentQueue) as QueueItem[];
|
|
// Prevent duplicate song/singer pairs
|
|
const duplicate = queueItems.find(item => item.song.path === song.path && item.singer.name === currentSinger);
|
|
if (duplicate) {
|
|
throw new Error('This song is already in the queue for this singer.');
|
|
}
|
|
const maxOrder = queueItems.length > 0
|
|
? Math.max(...queueItems.map(item => item.order || 0))
|
|
: 0;
|
|
const nextOrder = maxOrder + 1;
|
|
|
|
const queueItem: Omit<QueueItem, 'key'> = {
|
|
order: nextOrder,
|
|
singer: {
|
|
name: currentSinger,
|
|
lastLogin: new Date().toISOString(),
|
|
},
|
|
song,
|
|
};
|
|
|
|
await queueService.addToQueue(controllerName, queueItem);
|
|
} catch (error) {
|
|
handleFirebaseError(error, 'add song to queue');
|
|
throw error;
|
|
}
|
|
}, [controllerName, currentSinger, currentQueue, handleFirebaseError]);
|
|
|
|
const removeFromQueue = useCallback(async (queueItemKey: string) => {
|
|
if (!controllerName) {
|
|
throw new Error('Controller name not available');
|
|
}
|
|
|
|
try {
|
|
await queueService.removeFromQueue(controllerName, queueItemKey);
|
|
} catch (error) {
|
|
handleFirebaseError(error, 'remove song from queue');
|
|
throw error;
|
|
}
|
|
}, [controllerName, handleFirebaseError]);
|
|
|
|
const toggleFavorite = useCallback(async (song: Song) => {
|
|
if (!controllerName) {
|
|
throw new Error('Controller name not available');
|
|
}
|
|
|
|
try {
|
|
debugLog('toggleFavorite called for song:', song.title, song.path);
|
|
|
|
// Check if the song is currently in favorites by looking it up
|
|
const favoritesRef = ref(database, `controllers/${controllerName}/favorites`);
|
|
const snapshot = await get(favoritesRef);
|
|
const favorites = snapshot.exists() ? snapshot.val() : {};
|
|
|
|
debugLog('Current favorites:', favorites);
|
|
|
|
// Find if this song is already in favorites by matching the path
|
|
const existingFavoriteKey = Object.keys(favorites).find(key => {
|
|
const favoriteSong = favorites[key];
|
|
return favoriteSong && favoriteSong.path === song.path;
|
|
});
|
|
|
|
debugLog('Existing favorite key:', existingFavoriteKey);
|
|
|
|
if (existingFavoriteKey) {
|
|
// Remove from favorites
|
|
debugLog('Removing from favorites');
|
|
await favoritesService.removeFromFavorites(controllerName, existingFavoriteKey);
|
|
} else {
|
|
// Add to favorites
|
|
debugLog('Adding to favorites');
|
|
await favoritesService.addToFavorites(controllerName, song);
|
|
}
|
|
|
|
debugLog('toggleFavorite completed');
|
|
} catch (error) {
|
|
handleFirebaseError(error, 'toggle favorite');
|
|
throw error;
|
|
}
|
|
}, [controllerName, handleFirebaseError]);
|
|
|
|
const removeFromFavorites = useCallback(async (songKey: string) => {
|
|
if (!controllerName) {
|
|
throw new Error('Controller name not available');
|
|
}
|
|
|
|
try {
|
|
await favoritesService.removeFromFavorites(controllerName, songKey);
|
|
} catch (error) {
|
|
handleFirebaseError(error, 'remove from favorites');
|
|
throw error;
|
|
}
|
|
}, [controllerName, handleFirebaseError]);
|
|
|
|
return {
|
|
addToQueue,
|
|
removeFromQueue,
|
|
toggleFavorite,
|
|
removeFromFavorites,
|
|
canAddToQueue: !!controllerName && !!currentSinger,
|
|
};
|
|
};
|