Add Discogs artwork selection UI in album edit modal
Backend: - Add DiscogsImageOption struct for artwork options - Add discogs_search_artwork command to search multiple images - Add discogs_download_artwork command to download selected image - Extend DiscogsClient with search_artwork_options() method - Extend DiscogsClient with download_artwork_from_url() method - Register new commands in lib.rs Frontend: - Add Discogs image selection to album edit modal - Add 'Fetch from Discogs' button with Discogs logo - Display grid of artwork options from Discogs search results - Allow user to select preferred artwork option - Download and save selected artwork on Save - Add comprehensive CSS styling for Discogs UI elements - Adjust Discogs logo color filter for proper contrast User can now click 'Fetch from Discogs', browse multiple artwork options, select one, and save it as the album's cover art.
This commit is contained in:
1 parent
dd70f0a8c4
commit
dab5c28727
5 files changed
+315
-9
No files matched your search
@@ -32,6 +32,16 @@ pub struct SearchResult {
|
||||
pub result_type: String,
|
||||
}
|
||||
|
||||
/// Image option for artwork selection
|
||||
#[derive(Debug, Deserialize, serde::Serialize, Clone)]
|
||||
pub struct DiscogsImageOption {
|
||||
pub url: String,
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
#[serde(rename = "type")]
|
||||
pub image_type: String,
|
||||
}
|
||||
|
||||
impl DiscogsClient {
|
||||
/// Create a new Discogs client (proxy handles credentials)
|
||||
pub fn new() -> Self {
|
||||
@@ -135,6 +145,95 @@ impl DiscogsClient {
|
||||
None
|
||||
}
|
||||
|
||||
/// Search for album artwork options
|
||||
/// Returns up to 10 image options from the first matching release
|
||||
pub async fn search_artwork_options(
|
||||
&self,
|
||||
artist: &str,
|
||||
album: &str,
|
||||
) -> Result<Vec<DiscogsImageOption>, String> {
|
||||
// Build search query
|
||||
let query = format!("{} {}", artist, album);
|
||||
let url = format!(
|
||||
"{}/search?q={}&type=release",
|
||||
DISCOGS_PROXY_URL,
|
||||
urlencoding::encode(&query)
|
||||
);
|
||||
|
||||
log::debug!("Searching Discogs artwork options for: {} - {}", artist, album);
|
||||
|
||||
let response = self.client.get(&url).send().await
|
||||
.map_err(|e| format!("Failed to search Discogs: {}", e))?;
|
||||
|
||||
if !response.status().is_success() {
|
||||
return Err(format!("Discogs search failed with status: {}", response.status()));
|
||||
}
|
||||
|
||||
let search: SearchResponse = response.json().await
|
||||
.map_err(|e| format!("Failed to parse Discogs response: {}", e))?;
|
||||
|
||||
// Collect image options from search results
|
||||
let mut images = Vec::new();
|
||||
|
||||
for result in search.results.iter().take(10) {
|
||||
if result.result_type == "release" || result.result_type == "master" {
|
||||
// Add cover image if available
|
||||
if let Some(cover) = &result.cover_image {
|
||||
if !cover.is_empty() && !cover.contains("spacer.gif") {
|
||||
images.push(DiscogsImageOption {
|
||||
url: cover.clone(),
|
||||
width: 600, // Discogs standard size
|
||||
height: 600,
|
||||
image_type: "primary".to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add thumbnail as alternative
|
||||
if let Some(thumb) = &result.thumb {
|
||||
if !thumb.is_empty() && !thumb.contains("spacer.gif") {
|
||||
images.push(DiscogsImageOption {
|
||||
url: thumb.clone(),
|
||||
width: 150, // Discogs thumb size
|
||||
height: 150,
|
||||
image_type: "secondary".to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if images.is_empty() {
|
||||
return Err("No artwork found on Discogs".to_string());
|
||||
}
|
||||
|
||||
// Return up to 10 unique images
|
||||
images.truncate(10);
|
||||
Ok(images)
|
||||
}
|
||||
|
||||
/// Download image from URL and return local path
|
||||
pub async fn download_artwork_from_url(
|
||||
&self,
|
||||
image_url: &str,
|
||||
cache_dir: &Path,
|
||||
artist: &str,
|
||||
album: &str,
|
||||
) -> Result<String, String> {
|
||||
// Generate cache filename
|
||||
let filename = format!(
|
||||
"discogs_{:x}.jpg",
|
||||
Self::simple_hash(&format!("{}_{}", artist, album))
|
||||
);
|
||||
let cache_path = cache_dir.join(&filename);
|
||||
|
||||
// Download the image
|
||||
self.download_image(image_url, &cache_path).await
|
||||
.ok_or_else(|| "Failed to download image".to_string())?;
|
||||
|
||||
Ok(cache_path.to_string_lossy().to_string())
|
||||
}
|
||||
|
||||
/// Search for artists and return search results
|
||||
pub async fn search_artist(&self, query: &str) -> Result<SearchResponse, String> {
|
||||
let url = format!(
|
||||
|
||||
@@ -417,6 +417,8 @@ pub fn run() {
|
||||
// Discogs artwork commands
|
||||
library::commands::discogs_has_credentials,
|
||||
library::commands::discogs_search_artist,
|
||||
library::commands::discogs_search_artwork,
|
||||
library::commands::discogs_download_artwork,
|
||||
library::commands::library_fetch_missing_artwork,
|
||||
library::commands::library_fetch_album_artwork,
|
||||
library::commands::library_set_album_artwork,
|
||||
|
||||
@@ -1712,3 +1712,32 @@ pub async fn playlist_get_offline_available(
|
||||
|
||||
Ok(playlists.iter().map(|p| p.qobuz_playlist_id).collect())
|
||||
}
|
||||
|
||||
// === Discogs Artwork ===
|
||||
|
||||
/// Search Discogs for artwork options
|
||||
#[tauri::command]
|
||||
pub async fn discogs_search_artwork(
|
||||
artist: String,
|
||||
album: String,
|
||||
) -> Result<Vec<crate::discogs::DiscogsImageOption>, String> {
|
||||
log::info!("Command: discogs_search_artwork {} - {}", artist, album);
|
||||
|
||||
let client = DiscogsClient::new();
|
||||
client.search_artwork_options(&artist, &album).await
|
||||
}
|
||||
|
||||
/// Download and save Discogs artwork
|
||||
#[tauri::command]
|
||||
pub async fn discogs_download_artwork(
|
||||
image_url: String,
|
||||
artist: String,
|
||||
album: String,
|
||||
) -> Result<String, String> {
|
||||
log::info!("Command: discogs_download_artwork from {}", image_url);
|
||||
|
||||
let cache_dir = get_artwork_cache_dir();
|
||||
let client = DiscogsClient::new();
|
||||
|
||||
client.download_artwork_from_url(&image_url, &cache_dir, &artist, &album).await
|
||||
}
|
||||
Reference in new issue
Block a user