/* This file is part of jellything (https://codeberg.org/metamuffin/jellything) which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2026 metamuffin */ use jellyui_locale::tr; use std::fmt::Write; pub fn format_duration(d: f64) -> String { format_duration_mode("en", d, false) } pub fn format_duration_long(lang: &str, d: f64) -> String { format_duration_mode(lang, d, true) } fn format_duration_mode(lang: &str, mut d: f64, long_units: bool) -> String { let mut s = String::new(); let sign = if d > 0. { "" } else { "-" }; d = d.abs(); for (short, long, long_pl, k) in [ ("d", "time.day", "time.days", 60. * 60. * 24.), ("h", "time.hour", "time.hours", 60. * 60.), ("m", "time.minute", "time.minutes", 60.), ("s", "time.second", "time.seconds", 1.), ] { let h = (d / k).floor(); d -= h * k; if h > 0. { if long_units { let long = tr(lang, if h != 1. { long_pl } else { long }); let and = format!(" {} ", tr(lang, "time.and_join")); // TODO breaks if seconds is zero write!( s, "{}{h} {long}{}", if k != 1. { "" } else { &and }, if k > 60. { ", " } else { "" }, ) .unwrap(); } else { write!(s, "{h}{short} ").unwrap(); } } } format!("{sign}{}", s.trim()) } #[test] fn test_duration_short() { assert_eq!(format_duration(61.).as_str(), "1m 1s"); assert_eq!(format_duration(3661.).as_str(), "1h 1m 1s"); } #[test] fn test_duration_long() { assert_eq!( format_duration_long("en", 61.).as_str(), "1 minute and 1 second" ); assert_eq!( format_duration_long("en", 121.).as_str(), "2 minutes and 1 second" ); assert_eq!( format_duration_long("en", 3661.).as_str(), "1 hour, 1 minute and 1 second" ); } pub fn format_size(size: u64) -> String { humansize::format_size(size, humansize::DECIMAL) } // pub fn node_resolution_name(node: &Object) -> &'static str { // let mut maxdim = 0; // for t in node.iter(NO_TRACK) { // if let Some(width) = t.get(TR_PIXEL_WIDTH) { // maxdim = maxdim.max(width) // } // if let Some(height) = t.get(TR_PIXEL_HEIGHT) { // maxdim = maxdim.max(height) // } // } // match maxdim { // 30720.. => "32K", // 15360.. => "16K", // 7680.. => "8K UHD", // 5120.. => "5K UHD", // 3840.. => "4K UHD", // 2560.. => "QHD 1440p", // 1920.. => "FHD 1080p", // 1280.. => "HD 720p", // 854.. => "SD 480p", // _ => "Unkown", // } // } pub fn format_count(n: impl Into) -> String { let n: usize = n.into(); if n >= 1_000_000 { format!("{:.1}M", n as f32 / 1_000_000.) } else if n >= 1_000 { format!("{:.1}k", n as f32 / 1_000.) } else { format!("{n}") } } // pub fn format_chapter(c: &Object) -> (String, String) { // ( // format!( // "{}-{}", // c.get(CH_START).map(format_duration).unwrap_or_default(), // c.get(CH_END).map(format_duration).unwrap_or_default(), // ), // c.get(CH_NAME).unwrap_or_default().to_string(), // ) // }