Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions src-tauri/crates/app/src/commands/browse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,23 @@ pub struct AlbumTrack {
/// for DSF/DFF tracks where bit_depth=1 would otherwise look
/// like junk to the badge logic.
pub codec: Option<String>,
// The remaining fields exist so the Properties modal opened from
// this view shows the same Audio / File sections it shows
// everywhere else. AlbumDetailView has to synthesise a full
// `Track` for the context menu, and anything missing here became
// a hard-coded null there — which is exactly what left those
// sections blank on the album page only (issue #458).
pub year: Option<i64>,
pub bitrate: Option<i64>,
pub channels: Option<i64>,
pub musical_key: Option<String>,
pub file_size: i64,
pub added_at: i64,
/// Half-star rating (POPM round-trip). Selected so the context
/// menu's rating submenu reflects reality here: it is enabled by
/// default, so a hard-coded `null` made an already-rated track
/// read as unrated on this view.
pub rating: Option<i64>,
}

#[derive(FromRow)]
Expand All @@ -988,6 +1005,13 @@ struct AlbumTrackRaw {
bit_depth: Option<i64>,
sample_rate: Option<i64>,
codec: Option<String>,
year: Option<i64>,
bitrate: Option<i64>,
channels: Option<i64>,
musical_key: Option<String>,
file_size: i64,
added_at: i64,
rating: Option<i64>,
}

/// Return full album detail: header (with Deezer-cached label), genres,
Expand Down Expand Up @@ -1094,6 +1118,8 @@ pub async fn get_album_detail(
t.duration_ms, t.track_number, t.disc_number,
t.file_path,
t.bit_depth, t.sample_rate, t.codec,
t.year, t.bitrate, t.channels, t.musical_key,
t.file_size, t.added_at, t.rating,
aw.hash AS artwork_hash, aw.format AS artwork_format
FROM ranked r
JOIN track t ON t.id = r.id
Expand Down Expand Up @@ -1138,6 +1164,13 @@ pub async fn get_album_detail(
bit_depth: row.bit_depth,
sample_rate: row.sample_rate,
codec: row.codec,
year: row.year,
bitrate: row.bitrate,
channels: row.channels,
musical_key: row.musical_key,
file_size: row.file_size,
added_at: row.added_at,
rating: row.rating,
}
})
.collect();
Expand Down
29 changes: 20 additions & 9 deletions src/components/views/AlbumDetailView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,16 @@ export function AlbumDetailView({

if (!album) return <DetailViewSkeleton ariaLabel={t("albumDetail.badge")} />; // loading

// Build playable Track[] from AlbumTrack[] for the player
// Build playable Track[] from AlbumTrack[] for the player AND for the
// track context menu — which is what feeds the Properties modal. Every
// field the modal reads must come from the row rather than a
// placeholder: hard-coded nulls here are what left the Audio and File
// sections blank on this view alone (issue #458).
//
// That includes `rating`: the context menu's rating submenu is on by
// default here, so the previous placeholder made an already-rated
// track show up as unrated — the exact misreport `enableRating:
// false` exists to prevent on surfaces that genuinely lack it.
const playableTracks = album.tracks.map((at) => ({
id: at.id,
library_id: 0,
Expand All @@ -182,20 +191,22 @@ export function AlbumDetailView({
duration_ms: at.duration_ms,
track_number: at.track_number,
disc_number: at.disc_number,
year: album.year,
bitrate: null,
// The track's own year, falling back to the album's — a
// compilation can carry a per-track year the album header doesn't.
year: at.year ?? album.year,
bitrate: at.bitrate,
sample_rate: at.sample_rate,
channels: null,
channels: at.channels,
bit_depth: at.bit_depth,
codec: null,
musical_key: null,
codec: at.codec,
musical_key: at.musical_key,
file_path: at.file_path,
file_size: 0,
added_at: 0,
file_size: at.file_size,
added_at: at.added_at,
artwork_path: at.artwork_path,
artwork_path_1x: at.artwork_path_1x,
artwork_path_2x: at.artwork_path_2x,
rating: null,
rating: at.rating,
}));

const handlePlayAll = async () => {
Expand Down
13 changes: 13 additions & 0 deletions src/lib/tauri/detail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@ export interface AlbumTrack {
bit_depth: number | null;
sample_rate: number | null;
codec: string | null;
/** Carried so AlbumDetailView can build a complete `Track` for the
* context menu — the Properties modal reads these, and anything
* missing here used to be hard-coded to null there (issue #458). */
year: number | null;
bitrate: number | null;
channels: number | null;
musical_key: string | null;
file_size: number;
added_at: number;
/** Half-star rating. The context menu's rating submenu is on by
* default, so a placeholder here made a rated track read as
* unrated on the album page. */
rating: number | null;
}

export interface AlbumDetail {
Expand Down