Add source/qobuz_track_id to LocalTrack model and implement filtering for Artists/Tracks
- Added source and qobuz_track_id fields to LocalTrack model for proper filtering - Updated all database row mapping functions to include new fields - Implemented network folder and download filtering for library_get_artists command - Implemented network folder and download filtering for library_search (Tracks) command - Made tab counters (Albums, Artists, Tracks) reactive to filtered content - Counters now update based on current filtered data instead of total stats Fixes offline mode filtering for Artists and Tracks tabs. When offline or when downloads are hidden, Artists/Tracks now properly filter out inaccessible content, matching the behavior already implemented for Albums.
This commit is contained in:
1 parent
1347c11fcc
commit
2270d80139
6 files changed
+152
-14
No files matched your search
@@ -848,24 +848,116 @@ pub async fn library_get_album_tracks(
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn library_get_artists(state: State<'_, LibraryState>) -> Result<Vec<LocalArtist>, String> {
|
||||
log::info!("Command: library_get_artists");
|
||||
pub async fn library_get_artists(
|
||||
exclude_network_folders: Option<bool>,
|
||||
state: State<'_, LibraryState>,
|
||||
download_settings_state: State<'_, crate::config::DownloadSettingsState>,
|
||||
) -> Result<Vec<LocalArtist>, String> {
|
||||
log::info!("Command: library_get_artists (exclude_network: {:?})", exclude_network_folders);
|
||||
|
||||
// Get download settings
|
||||
let include_qobuz = download_settings_state
|
||||
.lock()
|
||||
.map_err(|e| format!("Failed to lock download settings: {}", e))?
|
||||
.get_settings()
|
||||
.map(|s| s.show_in_library)
|
||||
.unwrap_or(false);
|
||||
|
||||
let db = state.db.lock().await;
|
||||
db.get_artists().map_err(|e| e.to_string())
|
||||
let mut artists = db.get_artists().map_err(|e| e.to_string())?;
|
||||
|
||||
// Filter artists based on their tracks
|
||||
if exclude_network_folders.unwrap_or(false) || !include_qobuz {
|
||||
let network_folders = if exclude_network_folders.unwrap_or(false) {
|
||||
db.get_network_folder_paths().map_err(|e| e.to_string())?
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
artists.retain(|artist| {
|
||||
// Get all tracks for this artist
|
||||
if let Ok(tracks) = db.search(&artist.name, 10000) {
|
||||
// Check if artist has at least one valid track
|
||||
tracks.iter().any(|track| {
|
||||
// Check download filter
|
||||
let passes_download_filter = if include_qobuz {
|
||||
true
|
||||
} else {
|
||||
// Only include if NOT a qobuz download
|
||||
track.source.as_deref() != Some("qobuz_download")
|
||||
};
|
||||
|
||||
// Check network folder filter
|
||||
let passes_network_filter = if exclude_network_folders.unwrap_or(false) && !network_folders.is_empty() {
|
||||
// Only include if NOT in network folder
|
||||
!network_folders.iter().any(|folder_path| track.file_path.starts_with(folder_path))
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
||||
passes_download_filter && passes_network_filter
|
||||
})
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Ok(artists)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn library_search(
|
||||
query: String,
|
||||
limit: Option<u32>,
|
||||
exclude_network_folders: Option<bool>,
|
||||
state: State<'_, LibraryState>,
|
||||
download_settings_state: State<'_, crate::config::DownloadSettingsState>,
|
||||
) -> Result<Vec<LocalTrack>, String> {
|
||||
log::info!("Command: library_search \"{}\"", query);
|
||||
log::info!("Command: library_search \"{}\" (exclude_network: {:?})", query, exclude_network_folders);
|
||||
|
||||
// Get download settings
|
||||
let include_qobuz = download_settings_state
|
||||
.lock()
|
||||
.map_err(|e| format!("Failed to lock download settings: {}", e))?
|
||||
.get_settings()
|
||||
.map(|s| s.show_in_library)
|
||||
.unwrap_or(false);
|
||||
|
||||
let db = state.db.lock().await;
|
||||
db.search(&query, limit.unwrap_or(50))
|
||||
.map_err(|e| e.to_string())
|
||||
let mut tracks = db.search(&query, limit.unwrap_or(50))
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
// Filter tracks
|
||||
if exclude_network_folders.unwrap_or(false) || !include_qobuz {
|
||||
let network_folders = if exclude_network_folders.unwrap_or(false) {
|
||||
db.get_network_folder_paths().map_err(|e| e.to_string())?
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
tracks.retain(|track| {
|
||||
// Check download filter
|
||||
let passes_download_filter = if include_qobuz {
|
||||
true
|
||||
} else {
|
||||
// Only include if NOT a qobuz download
|
||||
track.source.as_deref() != Some("qobuz_download")
|
||||
};
|
||||
|
||||
// Check network folder filter
|
||||
let passes_network_filter = if exclude_network_folders.unwrap_or(false) && !network_folders.is_empty() {
|
||||
// Only include if NOT in network folder
|
||||
!network_folders.iter().any(|folder_path| track.file_path.starts_with(folder_path))
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
||||
passes_download_filter && passes_network_filter
|
||||
});
|
||||
}
|
||||
|
||||
Ok(tracks)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
|
||||
@@ -270,6 +270,8 @@ pub fn cue_to_tracks(
|
||||
artwork_path: None,
|
||||
last_modified: 0,
|
||||
indexed_at: now,
|
||||
source: None,
|
||||
qobuz_track_id: None,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1218,6 +1218,8 @@ impl LibraryDatabase {
|
||||
artwork_path: row.get(19)?,
|
||||
last_modified: row.get(20)?,
|
||||
indexed_at: row.get(21)?,
|
||||
source: row.get(24).ok().flatten(),
|
||||
qobuz_track_id: row.get(25).ok().flatten(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1788,7 +1790,8 @@ impl LibraryDatabase {
|
||||
t.album_group_key, t.album_group_title, t.track_number, t.disc_number,
|
||||
t.year, t.genre, t.duration_secs, t.format, t.bit_depth, t.sample_rate,
|
||||
t.channels, t.file_size_bytes, t.cue_file_path, t.cue_start_secs,
|
||||
t.cue_end_secs, t.artwork_path, t.last_modified, t.indexed_at, plt.position
|
||||
t.cue_end_secs, t.artwork_path, t.last_modified, t.indexed_at, t.source,
|
||||
t.qobuz_track_id, plt.position
|
||||
FROM playlist_local_tracks plt
|
||||
JOIN local_tracks t ON plt.local_track_id = t.id
|
||||
WHERE plt.qobuz_playlist_id = ?1
|
||||
@@ -1822,6 +1825,8 @@ impl LibraryDatabase {
|
||||
artwork_path: row.get(21)?,
|
||||
last_modified: row.get(22)?,
|
||||
indexed_at: row.get(23)?,
|
||||
source: row.get(24)?,
|
||||
qobuz_track_id: row.get(25)?,
|
||||
})
|
||||
}).map_err(|e| LibraryError::Database(format!("Failed to query playlist local tracks: {}", e)))?;
|
||||
|
||||
@@ -1836,7 +1841,8 @@ impl LibraryDatabase {
|
||||
t.album_group_key, t.album_group_title, t.track_number, t.disc_number,
|
||||
t.year, t.genre, t.duration_secs, t.format, t.bit_depth, t.sample_rate,
|
||||
t.channels, t.file_size_bytes, t.cue_file_path, t.cue_start_secs,
|
||||
t.cue_end_secs, t.artwork_path, t.last_modified, t.indexed_at, plt.position
|
||||
t.cue_end_secs, t.artwork_path, t.last_modified, t.indexed_at, t.source,
|
||||
t.qobuz_track_id, plt.position
|
||||
FROM playlist_local_tracks plt
|
||||
JOIN local_tracks t ON plt.local_track_id = t.id
|
||||
WHERE plt.qobuz_playlist_id = ?1
|
||||
@@ -1871,8 +1877,10 @@ impl LibraryDatabase {
|
||||
artwork_path: row.get(21)?,
|
||||
last_modified: row.get(22)?,
|
||||
indexed_at: row.get(23)?,
|
||||
source: row.get(24)?,
|
||||
qobuz_track_id: row.get(25)?,
|
||||
},
|
||||
playlist_position: row.get(24)?,
|
||||
playlist_position: row.get(26)?,
|
||||
})
|
||||
}).map_err(|e| LibraryError::Database(format!("Failed to query playlist local tracks with position: {}", e)))?;
|
||||
|
||||
|
||||
@@ -341,6 +341,8 @@ impl MetadataExtractor {
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.map(|d| d.as_secs() as i64)
|
||||
.unwrap_or(0),
|
||||
source: None,
|
||||
qobuz_track_id: None,
|
||||
}
|
||||
} else {
|
||||
// No tag found, use defaults
|
||||
@@ -380,6 +382,8 @@ impl MetadataExtractor {
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.map(|d| d.as_secs() as i64)
|
||||
.unwrap_or(0),
|
||||
source: None,
|
||||
qobuz_track_id: None,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -72,6 +72,10 @@ pub struct LocalTrack {
|
||||
// Indexing
|
||||
pub last_modified: i64,
|
||||
pub indexed_at: i64,
|
||||
|
||||
// Download tracking
|
||||
pub source: Option<String>,
|
||||
pub qobuz_track_id: Option<i64>,
|
||||
}
|
||||
|
||||
impl Default for LocalTrack {
|
||||
@@ -102,6 +106,8 @@ impl Default for LocalTrack {
|
||||
artwork_path: None,
|
||||
last_modified: 0,
|
||||
indexed_at: 0,
|
||||
source: None,
|
||||
qobuz_track_id: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user