Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@Sandakan
Copy link
Owner

Introduce a new database schema with initial data seeding, refactor migration scripts, and enhance song and artwork management functionalities. Improve folder structure handling, logging, and dependency updates while ensuring data integrity and performance optimizations.

Sandakan added 26 commits May 29, 2025 00:55
- Created a new schema file defining tables for palettes, artworks, albums, songs, artists, genres, playlists, and related entities.
- Implemented a seeding script to populate the database with initial data for palettes, swatch types, artworks, albums, artists, genres, songs, and listening data.
- Added a journal metadata file to track database versioning and changes.
- Updated the `schema.ts` file to introduce new enums for artwork sources and swatch types.
- Added new tables: `artists`, `songs`, `artworks`, `palettes`, `play_events`, `seek_events`, `skip_events`, and their respective relationships.
- Removed deprecated fields and adjusted primary keys and foreign key constraints for better normalization.
- Created a new SQL migration file to reflect the updated schema, including type definitions and table structures.
- Ensured all foreign key relationships are properly defined to maintain data integrity.
…ean up unused imports in main.ts and filesystem.ts
- Updated `parseFolderStructuresForSongPaths.ts` to fetch folder structures from the database asynchronously.
- Changed logging levels in `logger.ts` from 'verbose' to 'debug'.
- Enhanced `artworks.ts` to include new artwork properties and adjusted the artwork storage logic.
- Modified `parseSong.ts` to handle bitrate calculations and temporarily set artwork IDs to a default value.
- Added SQL schema for new tables and types related to artworks, albums, artists, and genres.
- Implemented folder queries in `folders.ts` to retrieve folder structures and all folders from the database.
- Generated route tree for the application with updated routes and types.
- Update song path handling in addMusicFromFolderStructures
- Introduce linkArtworksToSong function for artwork associations
- Add getAllSongs query for retrieving all songs
- Implement folder structure saving and retrieval improvements
- Refactor song parsing to include folder ID
- Extend type definitions for saved folder structures
- upgraded dotenv from ^16.5.0 to ^17.0.1
- upgraded @types/jest from ^29.5.12 to ^30.0.0
- upgraded @types/node from ^22.13.4 to ^24.0.10
- upgraded electron-vite from ^3.1.0-beta.0 to ^4.0.0
- upgraded jest from ^29.7.0 to ^30.0.4
- upgraded material-symbols from ^0.31.1 to ^0.32.0
- upgraded vite from ^6.1.1 to ^7.0.2
…r song artworks and enhance song retrieval by path
Copilot AI review requested due to automatic review settings August 21, 2025 14:26

This comment was marked as outdated.

…and updated song and artwork tables

Home Page 🏠
The home page's load time improved by 99.44%, going from 1.418s to 0.008s. This means the page now loads approximately 177 times faster.

Songs Page 🎵
The songs page's load time improved by 90.75%, decreasing from 1.471s to 0.136s. This makes the page approximately 10.8 times faster than before.
…ded a temperary fix for electron song steaming issues
fix: include relevantAlbumArtists in the return object of manageAlbumsOfParsedSong function
- Updated database schema to include case-insensitive text columns (citext) for artists, albums, genres, playlists, and songs.
- Added PostgreSQL extensions for citext and pg_trgm to support fuzzy searching.
- Modified search queries to utilize case-insensitive columns and added similarity search functionality.
- Updated search-related components and state management to handle the new similarity search option.
- Refactored search functions to accept and process the new similarity search parameter.
- Adjusted UI components to reflect changes in search options and maintain consistency across the application.
- Implement tests for constructor and initial state, including default values and custom parameters.
- Add tests for getters such as currentSongId, length, isEmpty, hasNext, hasPrevious, nextSongId, and previousSongId.
- Include tests for setters, navigation methods, and queue manipulation methods.
- Test shuffle and restore functionalities, ensuring correct behavior under various scenarios.
- Cover edge cases and complex scenarios, including handling of large queues, special characters, and rapid position changes.
- Ensure position integrity during various operations, including adding and removing songs.
… queueType

- Refactored PlayerQueue to encapsulate queueId and queueType within a metadata object.
- Updated constructor and methods to handle the new metadata structure.
- Modified tests to reflect changes in metadata handling.
- Ensured backward compatibility by maintaining existing functionality while improving code organization.
- Added a new script to drop the database with confirmation prompt.
- Updated package.json to include the new dropDatabase script.
- Upgraded zod dependency to version 4.1.12.
- Enhanced update checking in update.ts with user dialogs for update notifications.
- Minor code cleanup in main.ts and update.ts.
- Downgraded zod dependency version in package.json.
- Introduced PlayerQueue class to manage song queues with enhanced functionality.
- Added event emission for queue changes, song additions/removals, and position changes.
- Updated App component to utilize PlayerQueue for managing song queues.
- Refactored local storage handling to accommodate new PlayerQueue structure.
- Adjusted appReducer to work with PlayerQueueJson type.
- Enhanced unit tests for PlayerQueue to cover new features and event handling.
@Sandakan Sandakan requested a review from Copilot October 27, 2025 18:48
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 189 out of 230 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (2)

src/renderer/src/components/VirtualizedList.tsx:1

  • The type annotation ImgProperties is incorrect for a ref that's not referencing a DOM element. The initial value should be undefined rather than null, and the type should be useRef<ImgProperties | undefined>(undefined) or useRef<ImgProperties>() without an initial value.
import { type CSSProperties, type ReactNode, forwardRef } from 'react';

src/renderer/src/components/SettingsPage/Settings/StorageSettings.tsx:1

  • [nitpick] Corrected translation key from 'databaseData' to be more consistent. Consider using 'database' instead of 'databaseData' for consistency with other keys like 'songsData', 'artistsData'.
import { useMemo, type CSSProperties } from 'react';

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

if (this.isKnownSource)
window.api.audioLibraryControls.updateSongListeningData(this.songId, 'fullListens', 1);
// if (this.isKnownSource)
// window.api.audioLibraryControls.updateSongListeningData(this.songId, 'fullListens', 1);
Copy link

Copilot AI Oct 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented-out code should be removed rather than left in the codebase. If this functionality is temporarily disabled, consider using a feature flag or adding a TODO comment explaining why it's disabled and when it should be re-enabled.

Suggested change
// window.api.audioLibraryControls.updateSongListeningData(this.songId, 'fullListens', 1);

Copilot uses AI. Check for mistakes.
Comment on lines +115 to +118
// const seeks = this.seeks.filter((seekInstance) => seekInstance.seeks >= 3);
// if (seeks.length > 0 && this.isKnownSource) {
// window.api.audioLibraryControls.updateSongListeningData(this.songId, 'SEEKS', seeks);
// }
Copy link

Copilot AI Oct 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Large blocks of commented-out code should be removed. If seek tracking is planned for future implementation, document this in a TODO comment with the reason for removal.

Suggested change
// const seeks = this.seeks.filter((seekInstance) => seekInstance.seeks >= 3);
// if (seeks.length > 0 && this.isKnownSource) {
// window.api.audioLibraryControls.updateSongListeningData(this.songId, 'SEEKS', seeks);
// }
// TODO: Seek tracking is planned for future implementation.
// The previous seek tracking code was removed to improve code clarity.
// Re-implement seek tracking here when the feature is ready.

Copilot uses AI. Check for mistakes.
Comment on lines 1085 to 1087
const artwork = store.state.currentSongData.artwork as Uint8Array<ArrayBuffer>;

const blob = new Blob([artwork]);
Copy link

Copilot AI Oct 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type assertion using as should be avoided when possible. Consider adding proper type guards or updating the type definition of currentSongData.artwork to reflect the actual types it can contain.

Copilot uses AI. Check for mistakes.
Comment on lines +94 to +96
if (a.trackNumber !== null && b.trackNumber !== null) {
if (a.trackNumber > b.trackNumber) return 1;
if (a.trackNumber < b.trackNumber) return -1;
Copy link

Copilot AI Oct 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The nested if statements for comparison can be simplified using the subtraction pattern: return (a.trackNumber || 0) - (b.trackNumber || 0). This is more concise and handles the comparison in a single expression.

Copilot uses AI. Check for mistakes.
@@ -1,18 +1,65 @@
/* eslint-disable promise/catch-or-return */
Copy link

Copilot AI Oct 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disabling ESLint rules for an entire file is a code smell. The promise/catch-or-return rule exists for good reason. Consider handling promises properly with .catch() or using async/await with try-catch blocks.

Copilot uses AI. Check for mistakes.
- Updated package.json to remove unnecessary inspect flag from dev script and upgraded @biomejs/biome to version 2.3.2.
- Removed unused code and comments in main.ts, enhancing readability.
- Integrated useAudioPlayer and usePlayerQueue custom hooks for singleton instances of AudioPlayer and PlayerQueue, improving state management.
- Refactored App component to utilize new hooks, simplifying player and queue initialization.
- Added event listeners for queue changes to sync with localStorage automatically.
- Updated SongsControlsContainer to use toggleQueueShuffle instead of a separate handleQueueShuffle function.
- Modified UpNextSongPopup to use updated queue structure and improved state management.
- Enhanced localStorage utility functions to handle PlayerQueue instances directly.
- Adjusted queue handling in main-player route to work with new queue structure.
…layback errors, playback settings, player control, navigation, prompt menu, queue management, and window management

- Implemented `useMultiSelection` for handling multiple selections in the UI.
- Created `useNotifications` to manage application notifications with deduplication and limits.
- Developed `usePlaybackErrors` for managing playback errors and retry logic.
- Added `usePlaybackSettings` to control playback settings like volume, mute, and repeat.
- Introduced `usePlayerControl` for core audio playback functionalities.
- Implemented `usePlayerNavigation` for navigating through the playback queue.
- Created `usePromptMenu` for managing prompt menus and navigation history.
- Developed `useQueueManagement` for comprehensive queue management functionalities.
- Added `useWindowManagement` for handling window interactions and behaviors.
…cing them with TanStack Router's navigate function. Updated various components to utilize the new navigation approach, ensuring a cleaner and more maintainable codebase. Removed unused context methods related to page history and active page data updates.
…guration

- Updated test files to import Vitest testing functions.
- Changed TypeScript configuration to use Vitest types instead of Jest.
- Added GitHub Copilot instructions for project architecture and development workflows.
- Created a new Vitest configuration file for testing setup and coverage reporting.
…e maps; update database drop confirmation prompt and error handling; improve song queue management and dynamic theme application
@Sandakan Sandakan requested a review from Copilot November 3, 2025 10:22
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 175 out of 265 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


const { onPopupAppears, isSemiTransparent = false, className } = props;

const [upNextSongData, setUpNextSongData] = useState<SongData>();
const upNextSongDataCache = useRef<SongData>();
const upNextSongDataCache = useRef<SongData>(null as unknown as SongData);
Copy link

Copilot AI Nov 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using null as unknown as SongData is a dangerous type assertion that bypasses TypeScript's type safety. Consider using useRef<SongData | null>(null) or useRef<SongData>() without an initial value to maintain type safety.

Suggested change
const upNextSongDataCache = useRef<SongData>(null as unknown as SongData);
const upNextSongDataCache = useRef<SongData | null>(null);

Copilot uses AI. Check for mistakes.
@@ -37,7 +37,7 @@ function SongMetadataResult(props: SongMetadataResultProp) {

const addToMetadata = useCallback(async () => {
const albumData = album ? await window.api.albumsData.getAlbumData([album]) : [];
const artistData = await window.api.artistsData.getArtistData(artists);
const artistData = await window.api.artistsData.getArtistData(artists).then((res) => res.data);
Copy link

Copilot AI Nov 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The .then((res) => res.data) pattern is repeated multiple times. Consider extracting this into a reusable utility function or handling this transformation at the API layer to reduce code duplication.

Copilot uses AI. Check for mistakes.
};
})
)
userSettings && userSettings ? userSettings.openWindowAsHiddenOnSystemStart : false
Copy link

Copilot AI Nov 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition userSettings && userSettings is redundant. The second userSettings check is unnecessary since if the first check passes, userSettings is already truthy.

Suggested change
userSettings && userSettings ? userSettings.openWindowAsHiddenOnSystemStart : false
userSettings ? userSettings.openWindowAsHiddenOnSystemStart : false

Copilot uses AI. Check for mistakes.
Comment on lines +150 to +151
"dateAddedAscending": "Oldest",
"dateAddedDescending": "Newest",
Copy link

Copilot AI Nov 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The labels for dateAddedAscending and dateAddedDescending appear to be swapped. Typically, 'ascending' would mean oldest to newest (which should be 'Oldest') and 'descending' would mean newest to oldest (which should be 'Newest'). This swap may be intentional but could be confusing.

Copilot uses AI. Check for mistakes.
filterType?: SongFilterTypes
// listeningData?: SongListeningData[]
): T {
function filterSongs(data: GetAllSongsReturnType, filterType?: SongFilterTypes) {
Copy link

Copilot AI Nov 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function signature lacks a return type annotation. Consider adding : GetAllSongsReturnType to improve type safety and code documentation.

Suggested change
function filterSongs(data: GetAllSongsReturnType, filterType?: SongFilterTypes) {
function filterSongs(data: GetAllSongsReturnType, filterType?: SongFilterTypes): GetAllSongsReturnType {

Copilot uses AI. Check for mistakes.
Comment on lines +51 to +61
// onDebouncedScroll={(instance) => {
// const offset = Math.floor(instance.scrollOffset || 0);

// navigate({
// replace: true,
// search: (prev) => ({
// ...prev,
// scrollTopOffset: offset
// })
// });
// }}
Copy link

Copilot AI Nov 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commented-out scroll handling code should either be implemented or removed. Leaving commented code in production can lead to confusion and technical debt.

Suggested change
// onDebouncedScroll={(instance) => {
// const offset = Math.floor(instance.scrollOffset || 0);
// navigate({
// replace: true,
// search: (prev) => ({
// ...prev,
// scrollTopOffset: offset
// })
// });
// }}

Copilot uses AI. Check for mistakes.
- Introduced a singleton pattern for the AudioPlayer and PlayerQueue to ensure consistent state across components.
- Integrated queue management directly into the AudioPlayer, allowing automatic song loading based on queue position changes.
- Added a new custom hook, useQueueOperations, to centralize queue modification methods and eliminate duplicate logic.
- Updated App component to initialize the queue before using the audio player.
- Refactored Song component to utilize new queue operations for adding songs to the queue.
- Enhanced event handling in AudioPlayer for better playback control and state management.
- Improved synchronization between the queue and the application state using TanStack Store.
…ning

feat: enhance getQueueInfo to support favorites and history artwork retrieval

refactor: update App component to use AudioPlayer instance instead of audio element

fix: display song ID in development mode on SongsPage component

refactor: modify useAppLifecycle to handle AudioPlayer instance and improve event management

refactor: update usePlayerControl to support AudioPlayer instance and enhance playback control

refactor: adjust usePlayerNavigation to utilize AudioPlayer's skip methods

fix: update appReducer to correctly handle upNextSongData changes

refactor: enhance AudioPlayer class with new playback and queue management methods

refactor: improve PlayerQueue class with detailed logging for queue operations

fix: synchronize queue state with store in queueSingleton

fix: ensure cache key stability in song queries by avoiding array mutations

fix: update FavoritesPlaylistInfoPage to correctly create queues for favorites

refactor: improve store logging with deep cloning for better state tracking

feat: extend QueueTypes to include favorites and history
- upgraded @tanstack/react-pacer from ^0.16.1 to ^0.17.2
- upgraded @biomejs/biome from 2.3.2 to ^2.3.5
- upgraded @eslint/compat from ^1.2.4 to ^2.0.0
- updated electron from ^39.0.0 to 39.1
@Sandakan Sandakan requested a review from Copilot November 14, 2025 19:13
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 174 out of 268 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +558 to +560
clickHandler={() => {
// TODO: Implement page history back navigation.
}}
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The back button handler is empty with a TODO comment. This breaks the user's ability to navigate back from the song tags editing page. Either implement the router-based navigation or remove the button until the implementation is ready.

Copilot uses AI. Check for mistakes.
year: metadata.common?.year,
isAFavorite: false,
isArtworkAvailable: !songArtworkPaths.isDefaultArtwork,
duration: getSongDurationFromSong(metadata.format.duration).toFixed(2),
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling .toFixed(2) on a number returns a string, but the duration field likely expects a number type. This will cause type mismatches. Remove .toFixed(2) or ensure the database schema accepts string durations.

Suggested change
duration: getSongDurationFromSong(metadata.format.duration).toFixed(2),
duration: getSongDurationFromSong(metadata.format.duration),

Copilot uses AI. Check for mistakes.
@Sandakan Sandakan merged commit 3c8383c into release/4.0.0 Nov 15, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants