diff options
author | metamuffin <metamuffin@disroot.org> | 2025-04-28 00:48:52 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-04-28 00:48:52 +0200 |
commit | 80d28b764c95891551e28c395783f5ff9d065743 (patch) | |
tree | f25898b1c939a939c63236ca4e8e843e81069947 /ui/src/format.rs | |
parent | 335ba978dbaf203f3603a815147fd75dbf205723 (diff) | |
download | jellything-80d28b764c95891551e28c395783f5ff9d065743.tar jellything-80d28b764c95891551e28c395783f5ff9d065743.tar.bz2 jellything-80d28b764c95891551e28c395783f5ff9d065743.tar.zst |
start with splitting server
Diffstat (limited to 'ui/src/format.rs')
-rw-r--r-- | ui/src/format.rs | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/ui/src/format.rs b/ui/src/format.rs new file mode 100644 index 0000000..a374850 --- /dev/null +++ b/ui/src/format.rs @@ -0,0 +1,117 @@ +/* + 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) 2025 metamuffin <metamuffin.org> +*/ + +use crate::locale::{Language, TrString, tr, trs}; +use jellycommon::{Chapter, MediaInfo, NodeKind, SourceTrackKind}; + +pub fn format_duration(d: f64) -> String { + format_duration_mode(d, false, Language::English) +} +pub fn format_duration_long(d: f64, lang: Language) -> String { + format_duration_mode(d, true, lang) +} +fn format_duration_mode(mut d: f64, long_units: bool, lang: Language) -> 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()) +} +pub fn format_size(size: u64) -> String { + humansize::format_size(size, humansize::DECIMAL) +} +pub fn format_kind(k: NodeKind, lang: Language) -> TrString<'static> { + trs( + &lang, + match k { + NodeKind::Unknown => "kind.unknown", + NodeKind::Movie => "kind.movie", + NodeKind::Video => "kind.video", + NodeKind::Music => "kind.music", + NodeKind::ShortFormVideo => "kind.short_form_video", + NodeKind::Collection => "kind.collection", + NodeKind::Channel => "kind.channel", + NodeKind::Show => "kind.show", + NodeKind::Series => "kind.series", + NodeKind::Season => "kind.season", + NodeKind::Episode => "kind.episode", + }, + ) +} + +trait MediaInfoExt { + fn resolution_name(&self) -> &'static str; +} +impl MediaInfoExt for MediaInfo { + fn resolution_name(&self) -> &'static str { + let mut maxdim = 0; + for t in &self.tracks { + if let SourceTrackKind::Video { width, height, .. } = &t.kind { + maxdim = maxdim.max(*width.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<usize>) -> 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: &Chapter) -> (String, String) { + ( + format!( + "{}-{}", + c.time_start.map(format_duration).unwrap_or_default(), + c.time_end.map(format_duration).unwrap_or_default(), + ), + c.labels.first().map(|l| l.1.clone()).unwrap_or_default(), + ) +} |