Four wired surfaces on AlbumView, all previously inert stubs: - Cover menu (right-click, AlbumPageView.slint:300-370): Add/Change/Remove custom cover over the SAME custom_artwork.json store the Slint app uses (a cover set in one app shows in both), Open in browser, Save as…. Plus the NEW lightbox (menu entry + left-click): the art at its best available quality fitted to the window, custom override preferred. - Header action row: radio (the existing foryou_qt album-radio seam), booklet (visible when a PDF goody exists; downloads via save-as — no in-app reader, like the reference), and add-to-mixtape/collection — the MyQBZ picker's Accepts engine already lets albums target Collections (the Tauri rule), so the button just feeds it. - Album Info modal (the extensive one): fresh /album/get → credits grouped through the shared qbz_qobuz::performers parser, per-track copyright, review tab when the album has editorial text, label link, musician navigation, per-track play in album context. Tauri layout (left fixed meta column, right scrollable tabs) per the project ruling for this feature; the header's label link is wired along the way (LabelView has existed for a while — the POC-NOTE was stale). - … menu: Add to playlist (the loaded view's track ids into the picker), Add to mixtape, Share Qobuz link, Share Album.link (UPC -> Deezer -> album.link, #514 path — the resolver half of share.rs is now ported for the album arm). The offline rows stay out: no Qt album-cache seam. i18n: "View cover" + "Could not load the image" catalogued in all seven locales. Gate: both QML audits + 305 tests + debug/release builds green. km
74 lines
3.1 KiB
Rust
74 lines
3.1 KiB
Rust
//! Release-date label formatting for album cards (#469).
|
|
//!
|
|
//! Renders a Qobuz release date as a fixed "MMM D, YYYY" structure (e.g.
|
|
//! "Nov 6, 2025") with a *localized* abbreviated month. We deliberately keep
|
|
//! the month / day / year order fixed (not the locale-reordered output of a
|
|
//! `toLocaleDateString`-style call) but localize the month token, because the
|
|
//! app ships five UI languages (en / es / de / fr / pt). The Slint UI is
|
|
//! English-only during the migration, so [`current_locale`] returns English
|
|
//! today — it is the single place to wire the real UI language once Slint
|
|
//! gets translation support, and no caller needs to change when it does.
|
|
|
|
use chrono::{Locale, NaiveDate};
|
|
|
|
/// UI language used to render date labels. Maps the active runtime language
|
|
/// (`qbz_i18n::current_language()`, set at startup and on live switch) to the
|
|
/// matching `chrono` locale so month tokens localize with the rest of the UI.
|
|
/// The app supports en / es / de / fr / pt; unknown values fall back to English.
|
|
pub fn current_locale() -> Locale {
|
|
match qbz_i18n::current_language() {
|
|
"es" => Locale::es_ES,
|
|
"de" => Locale::de_DE,
|
|
"fr" => Locale::fr_FR,
|
|
"pt" => Locale::pt_PT,
|
|
_ => Locale::en_US,
|
|
}
|
|
}
|
|
|
|
/// Format a Qobuz release date string ("YYYY-MM-DD", possibly with a trailing
|
|
/// time component) as "MMM D, YYYY" with a localized month. Falls back to the
|
|
/// bare 4-digit year when only a year is available or the value cannot be
|
|
/// parsed as a full date, and to an empty string when there is no date.
|
|
pub fn release_label(date: Option<&str>) -> String {
|
|
let Some(raw) = date else {
|
|
return String::new();
|
|
};
|
|
let raw = raw.trim();
|
|
if raw.is_empty() {
|
|
return String::new();
|
|
}
|
|
// Only the leading YYYY-MM-DD matters; ignore any trailing time.
|
|
let head = raw.get(0..10).unwrap_or(raw);
|
|
if let Ok(parsed) = NaiveDate::parse_from_str(head, "%Y-%m-%d") {
|
|
// %b = localized abbreviated month, %-d = day without leading zero.
|
|
return parsed
|
|
.format_localized("%b %-d, %Y", current_locale())
|
|
.to_string();
|
|
}
|
|
// Year-only fallback (e.g. the source only had "2025").
|
|
raw.get(0..4).unwrap_or_default().to_string()
|
|
}
|
|
|
|
/// Format a Qobuz release date as "MMMM D, YYYY" (FULL localized month) —
|
|
/// the Album Info modal's "Released by … on <date>" line (Slint
|
|
/// `info_modals.rs::full_release_date`, Tauri `formatReleaseDate`). Empty
|
|
/// when the value is missing or unparseable (no year fallback here: the
|
|
/// header already shows the short form elsewhere).
|
|
pub fn full_release_label(date: Option<&str>) -> String {
|
|
let Some(raw) = date else {
|
|
return String::new();
|
|
};
|
|
let raw = raw.trim();
|
|
if raw.is_empty() {
|
|
return String::new();
|
|
}
|
|
let head = raw.get(0..10).unwrap_or(raw);
|
|
if let Ok(parsed) = NaiveDate::parse_from_str(head, "%Y-%m-%d") {
|
|
// %B = localized full month, %-d = day without leading zero.
|
|
return parsed
|
|
.format_localized("%B %-d, %Y", current_locale())
|
|
.to_string();
|
|
}
|
|
String::new()
|
|
}
|