aboutsummaryrefslogtreecommitdiff
path: root/ui/src/format.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-04-28 00:48:52 +0200
committermetamuffin <metamuffin@disroot.org>2025-04-28 00:48:52 +0200
commit80d28b764c95891551e28c395783f5ff9d065743 (patch)
treef25898b1c939a939c63236ca4e8e843e81069947 /ui/src/format.rs
parent335ba978dbaf203f3603a815147fd75dbf205723 (diff)
downloadjellything-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.rs117
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(),
+ )
+}