Improve web UI
All checks were successful
Build and Publish Deb Package / build-deb (push) Successful in 35s
Publish Server Image / build-and-push-image (push) Successful in 2m9s

This commit is contained in:
Ultradesu
2026-03-17 16:05:14 +00:00
parent cbc5639f99
commit 106ab96c56
11 changed files with 258 additions and 59 deletions

View File

@@ -137,28 +137,29 @@ fn extract_tags(
cover: &mut Option<(Vec<u8>, String)>,
) {
for tag in tags {
let value = fix_encoding(tag.value.to_string());
if let Some(key) = tag.std_key {
match key {
StandardTagKey::TrackTitle => {
*title = Some(tag.value.to_string());
*title = Some(value);
}
StandardTagKey::Artist | StandardTagKey::Performer => {
if artist.is_none() {
*artist = Some(tag.value.to_string());
*artist = Some(value);
}
}
StandardTagKey::Album => {
*album = Some(tag.value.to_string());
*album = Some(value);
}
StandardTagKey::TrackNumber => {
if track.is_none() {
*track = tag.value.to_string().parse().ok();
*track = value.parse().ok();
}
}
StandardTagKey::Date | StandardTagKey::OriginalDate => {
if year.is_none() {
// Parse first 4 characters as year
*year = tag.value.to_string()[..4.min(tag.value.to_string().len())].parse().ok();
*year = value[..4.min(value.len())].parse().ok();
}
}
_ => {}
@@ -173,3 +174,31 @@ fn extract_tags(
}
}
}
/// Heuristic to fix mojibake (CP1251 bytes interpreted as Latin-1/Windows-1252)
fn fix_encoding(s: String) -> String {
// If it's already a valid UTF-8 string that doesn't look like mojibake, return it.
// Mojibake looks like characters from Latin-1 Supplement (0xC0-0xFF)
// where they should be Cyrillic.
let bytes: Vec<u8> = s.chars().map(|c| c as u32).filter(|&c| c <= 255).map(|c| c as u8).collect();
// If the length is different, it means there were characters > 255, so it's not simple Latin-1 mojibake.
if bytes.len() != s.chars().count() {
return s;
}
// Check if it's likely CP1251. Russian characters in CP1251 are 0xC0-0xFF.
// In Latin-1 these are characters like À-ÿ.
let has_mojibake = bytes.iter().any(|&b| b >= 0xC0);
if !has_mojibake {
return s;
}
let (decoded, _, errors) = encoding_rs::WINDOWS_1251.decode(&bytes);
if errors {
return s;
}
decoded.into_owned()
}