aboutsummaryrefslogtreecommitdiff
path: root/server/src/ui/sort.rs
blob: 441bac63f4edabb4ee30ba025e086c372af21d25 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*
    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 jellycommon::{
    api::{FilterProperty, NodeFilterSort, SortOrder, SortProperty},
    helpers::SortAnyway,
    user::NodeUserData,
    Node, NodeKind, Rating,
};
use rocket::{
    http::uri::fmt::{Query, UriDisplay},
    FromForm, FromFormField, UriDisplayQuery,
};
use std::sync::Arc;

pub fn filter_and_sort_nodes(
    f: &NodeFilterSort,
    default_sort: (SortProperty, SortOrder),
    nodes: &mut Vec<(Arc<Node>, NodeUserData)>,
) {
    let sort_prop = f.sort_by.unwrap_or(default_sort.0);
    nodes.retain(|(node, _udata)| {
        let mut o = true;
        if let Some(prop) = &f.filter_kind {
            o = false;
            for p in prop {
                o |= match p {
                    // FilterProperty::FederationLocal => node.federated.is_none(),
                    // FilterProperty::FederationRemote => node.federated.is_some(),
                    FilterProperty::KindMovie => node.kind == NodeKind::Movie,
                    FilterProperty::KindVideo => node.kind == NodeKind::Video,
                    FilterProperty::KindShortFormVideo => node.kind == NodeKind::ShortFormVideo,
                    FilterProperty::KindMusic => node.kind == NodeKind::Music,
                    FilterProperty::KindCollection => node.kind == NodeKind::Collection,
                    FilterProperty::KindChannel => node.kind == NodeKind::Channel,
                    FilterProperty::KindShow => node.kind == NodeKind::Show,
                    FilterProperty::KindSeries => node.kind == NodeKind::Series,
                    FilterProperty::KindSeason => node.kind == NodeKind::Season,
                    FilterProperty::KindEpisode => node.kind == NodeKind::Episode,
                    // FilterProperty::Watched => udata.watched == WatchedState::Watched,
                    // FilterProperty::Unwatched => udata.watched == WatchedState::None,
                    // FilterProperty::WatchProgress => {
                    //     matches!(udata.watched, WatchedState::Progress(_))
                    // }
                    _ => false, // TODO
                }
            }
        }
        match sort_prop {
            SortProperty::ReleaseDate => o &= node.release_date.is_some(),
            SortProperty::Duration => o &= node.media.is_some(),
            _ => (),
        }
        o
    });
    match sort_prop {
        SortProperty::Duration => {
            nodes.sort_by_key(|(n, _)| (n.media.as_ref().unwrap().duration * 1000.) as i64)
        }
        SortProperty::ReleaseDate => {
            nodes.sort_by_key(|(n, _)| n.release_date.expect("asserted above"))
        }
        SortProperty::Title => nodes.sort_by(|(a, _), (b, _)| a.title.cmp(&b.title)),
        SortProperty::Index => nodes.sort_by(|(a, _), (b, _)| {
            a.index
                .unwrap_or(usize::MAX)
                .cmp(&b.index.unwrap_or(usize::MAX))
        }),
        SortProperty::RatingRottenTomatoes => nodes.sort_by_cached_key(|(n, _)| {
            SortAnyway(*n.ratings.get(&Rating::RottenTomatoes).unwrap_or(&0.))
        }),
        SortProperty::RatingMetacritic => nodes.sort_by_cached_key(|(n, _)| {
            SortAnyway(*n.ratings.get(&Rating::Metacritic).unwrap_or(&0.))
        }),
        SortProperty::RatingImdb => nodes
            .sort_by_cached_key(|(n, _)| SortAnyway(*n.ratings.get(&Rating::Imdb).unwrap_or(&0.))),
        SortProperty::RatingTmdb => nodes
            .sort_by_cached_key(|(n, _)| SortAnyway(*n.ratings.get(&Rating::Tmdb).unwrap_or(&0.))),
        SortProperty::RatingYoutubeViews => nodes.sort_by_cached_key(|(n, _)| {
            SortAnyway(*n.ratings.get(&Rating::YoutubeViews).unwrap_or(&0.))
        }),
        SortProperty::RatingYoutubeLikes => nodes.sort_by_cached_key(|(n, _)| {
            SortAnyway(*n.ratings.get(&Rating::YoutubeLikes).unwrap_or(&0.))
        }),
        SortProperty::RatingYoutubeFollowers => nodes.sort_by_cached_key(|(n, _)| {
            SortAnyway(*n.ratings.get(&Rating::YoutubeFollowers).unwrap_or(&0.))
        }),
        SortProperty::RatingLikesDivViews => nodes.sort_by_cached_key(|(n, _)| {
            SortAnyway(
                *n.ratings.get(&Rating::YoutubeLikes).unwrap_or(&0.)
                    / (1. + *n.ratings.get(&Rating::YoutubeViews).unwrap_or(&0.)),
            )
        }),
        SortProperty::RatingUser => nodes.sort_by_cached_key(|(_, u)| u.rating),
    }

    match f.sort_order.unwrap_or(default_sort.1) {
        SortOrder::Ascending => (),
        SortOrder::Descending => nodes.reverse(),
    }
}