feat: Implement localization support and update application version#9
feat: Implement localization support and update application version#9devohmycode merged 1 commit intomainfrom
Conversation
- Added a simple i18n system for language translations, allowing dynamic language switching. - Updated MainWindow and LibraryWindow to utilize localization for UI text. - Enhanced SettingsWindow to support language selection and display localized text. - Updated application version to 0.1.2 in installer.iss. - Improved README with instructions for adding new languages.
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (13)
📝 WalkthroughWalkthroughThis PR introduces internationalization (i18n) infrastructure with a translation dictionary system and language persistence, refactors UI elements across multiple windows to support dynamic localization via new Changes
Sequence DiagramsequenceDiagram
participant FS as File System
participant FW as FileSystemWatcher
participant LW as LibraryWatcher
participant LM as LibraryManager
participant UI as MainWindow
FS->>FW: File Created/Changed/Deleted
FW->>LW: OnChanged event
LW->>LW: Queue to pending map<br/>(debounce 600ms)
activate LW
Note over LW: Debounce timer fires
LW->>LW: Drain pending changes
rect rgba(100, 150, 200, 0.5)
Note over LW: For each file
alt Deletion
LW->>LM: RemoveTrackByPath(path)
LM-->>LW: bool success
else Creation/Modification
LW->>LM: AddOrUpdateFileAsync(filePath)
LM->>LM: Validate, ReadMetadata
LM->>LM: InsertTrack (transaction)
LM-->>LW: bool success
end
end
deactivate LW
alt Any operation succeeded
LW->>UI: LibraryChanged event
UI->>UI: LoadTracks() on UI thread
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Review Summary by QodoAdd localization support, real-time library watching, and responsive navigation
WalkthroughsDescription• Implemented comprehensive i18n localization system with English and French translations • Added real-time folder monitoring via LibraryWatcher for automatic library updates • Enhanced navigation UI with dynamic tab overflow handling and responsive layout • Integrated language selection in settings with persistent storage and UI refresh • Updated application version to 0.1.2 and improved documentation Diagramflowchart LR
A["Strings.cs<br/>i18n System"] -->|Translate| B["MainWindow<br/>UI Text"]
A -->|Translate| C["SettingsWindow<br/>UI Text"]
A -->|Translate| D["LibraryWindow<br/>UI Text"]
E["LibraryWatcher<br/>FileSystem Monitor"] -->|Detect Changes| F["LibraryManager<br/>Add/Remove Tracks"]
F -->|Notify| B
G["SettingsManager<br/>Language Persistence"] -->|Load/Save| A
H["NavOverflow Logic<br/>Responsive Tabs"] -->|Adapt| B
File Changes1. Audiomatic/Strings.cs
|
Code Review by Qodo
1. Watcher deletes playlist entries
|
| public static async Task<bool> AddOrUpdateFileAsync(string filePath) | ||
| { | ||
| var ext = Path.GetExtension(filePath).ToLowerInvariant(); | ||
| if (!AudioExtensions.Contains(ext)) return false; | ||
| if (!File.Exists(filePath)) return false; | ||
|
|
||
| var folders = GetFolders(); | ||
| var folder = folders | ||
| .Where(f => f.Enabled && filePath.StartsWith(f.Path, StringComparison.OrdinalIgnoreCase)) | ||
| .OrderByDescending(f => f.Path.Length) | ||
| .FirstOrDefault(); | ||
|
|
||
| if (folder == null) return false; | ||
|
|
||
| var track = await Task.Run(() => ReadMetadata(filePath, folder.Id)); | ||
|
|
||
| using var conn = new SqliteConnection(ConnectionString); | ||
| await conn.OpenAsync(); | ||
| EnablePragmas(conn); | ||
| using var transaction = conn.BeginTransaction(); | ||
| InsertTrack(conn, track, transaction); | ||
| transaction.Commit(); | ||
| return true; |
There was a problem hiding this comment.
1. Watcher deletes playlist entries 🐞 Bug ✓ Correctness
LibraryManager.AddOrUpdateFileAsync() updates tracks via InsertTrack() which uses `INSERT OR REPLACE, causing SQLite to delete and recreate rows when tracks.path` conflicts. Because playlist_tracks and favorites reference tracks(id) with ON DELETE CASCADE, a normal file change processed by LibraryWatcher can silently remove playlist membership and favorites for the affected track.
Agent Prompt
### Issue description
`AddOrUpdateFileAsync()` currently calls `InsertTrack()` which executes `INSERT OR REPLACE INTO tracks ...`. In SQLite, `OR REPLACE` deletes the existing row on a UNIQUE conflict (here: `tracks.path`), which triggers `ON DELETE CASCADE` on `playlist_tracks(track_id)` and `favorites(track_id)`, silently removing user data.
### Issue Context
- The watcher pathway will run frequently (Created/Changed events), making this data loss much more likely than manual rescans.
### Fix approach
- Replace the `INSERT OR REPLACE` behavior *for watcher-driven updates* with an UPSERT that preserves the existing rowid/`id`.
- Prefer SQLite `ON CONFLICT(path) DO UPDATE SET ...` so the existing row is updated in-place.
- Preserve `created_at` on updates (don’t overwrite it every time a file changes).
### Fix Focus Areas
- Audiomatic/Services/LibraryManager.cs[269-292]
- Audiomatic/Services/LibraryManager.cs[670-692]
- Audiomatic/Services/LibraryWatcher.cs[110-151]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| private void OnRenamed(object sender, RenamedEventArgs e) | ||
| { | ||
| QueueChange(e.OldFullPath, WatcherChangeType.Deleted); | ||
|
|
||
| var ext = Path.GetExtension(e.FullPath).ToLowerInvariant(); | ||
| if (LibraryManager.AudioExtensions.Contains(ext)) | ||
| QueueChange(e.FullPath, WatcherChangeType.Created); | ||
| } |
There was a problem hiding this comment.
2. Rename drops playlist links 🐞 Bug ✓ Correctness
LibraryWatcher.OnRenamed converts a rename into a delete of the old path plus a create of the new path. This removes the old tracks row (cascading to playlist_tracks/favorites) and then inserts a new track row, so renaming/moving a file within a watched folder can silently remove it from playlists and favorites.
Agent Prompt
### Issue description
File renames are currently treated as `DELETE oldPath` + `INSERT newPath`, which drops playlist/favorites relationships because they’re keyed by `track_id`.
### Issue Context
- `OnRenamed()` queues `Deleted` for `OldFullPath` and `Created` for the new file.
- `ProcessChanges()` maps `Deleted` to `RemoveTrackByPath()`.
### Fix approach
- Add a DB-level rename operation that preserves `tracks.id`, e.g. `UPDATE tracks SET path=@newPath, last_modified=@... WHERE path=@oldPath`.
- In `OnRenamed()`, queue a rename operation (or store a mapping) rather than delete+create.
- After path update, optionally refresh metadata for the new path (but using an in-place UPSERT/update that preserves ids).
### Fix Focus Areas
- Audiomatic/Services/LibraryWatcher.cs[81-88]
- Audiomatic/Services/LibraryWatcher.cs[110-151]
- Audiomatic/Services/LibraryManager.cs[657-693]
- Audiomatic/Services/LibraryManager.cs[42-85]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Summary by CodeRabbit
Release Notes
New Features
Chores