feat: Add export library button to front page - Add download icon button next to settings cog - Export current library to XML format compatible with Rekordbox - Auto-generate filename with current date - Disable button when no songs are available - Provides easy way to backup and share library data

This commit is contained in:
Geert Rademakes 2025-08-06 11:24:05 +02:00
parent 060d339e78
commit 1cba4e0eeb

View File

@ -1,5 +1,5 @@
import { Box, Button, Flex, Heading, Spinner, Text, useBreakpointValue, IconButton, Drawer, DrawerBody, DrawerHeader, DrawerOverlay, DrawerContent, useDisclosure, Modal, ModalOverlay, ModalContent, ModalHeader, ModalBody, ModalFooter, VStack } from "@chakra-ui/react";
import { ChevronLeftIcon, ChevronRightIcon, SettingsIcon } from "@chakra-ui/icons";
import { ChevronLeftIcon, ChevronRightIcon, SettingsIcon, DownloadIcon } from "@chakra-ui/icons";
import React, { useState, useRef, useEffect, useCallback } from "react";
import { useNavigate, useLocation, Routes, Route } from "react-router-dom";
import { PaginatedSongList } from "./components/PaginatedSongList";
@ -9,6 +9,7 @@ import { Configuration } from "./pages/Configuration";
import { useXmlParser } from "./hooks/useXmlParser";
import { usePaginatedSongs } from "./hooks/usePaginatedSongs";
import { formatTotalDuration } from "./utils/formatters";
import { exportToXml } from "./services/xmlService";
import { api } from "./services/api";
import type { Song, PlaylistNode } from "./types/interfaces";
@ -114,6 +115,24 @@ export default function RekordboxReader() {
searchQuery
} = usePaginatedSongs({ pageSize: 50, playlistName: currentPlaylist });
// Export library to XML
const handleExportLibrary = useCallback(() => {
try {
const xmlContent = exportToXml(songs, playlists);
const blob = new Blob([xmlContent], { type: 'application/xml' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `rekordbox-library-${new Date().toISOString().split('T')[0]}.xml`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
} catch (error) {
console.error('Failed to export library:', error);
}
}, [songs, playlists]);
// Check if database is initialized (has songs or playlists) - moved after useDisclosure
useEffect(() => {
const checkDatabaseInitialized = async () => {
@ -464,12 +483,24 @@ export default function RekordboxReader() {
Rekordbox Reader
</Heading>
{/* Export Library Button */}
<IconButton
icon={<DownloadIcon />}
aria-label="Export Library"
variant="ghost"
ml="auto"
mr={2}
color="gray.300"
_hover={{ color: "white", bg: "whiteAlpha.200" }}
onClick={handleExportLibrary}
isDisabled={songs.length === 0}
/>
{/* Configuration Button */}
<IconButton
icon={<SettingsIcon />}
aria-label="Configuration"
variant="ghost"
ml="auto"
color="gray.300"
_hover={{ color: "white", bg: "whiteAlpha.200" }}
onClick={() => navigate('/config')}