about summary refs log tree commit diff stats
path: root/crates/yt/src/commands/select/implm/standalone/mod.rs
blob: dd6de455be8d7b3d595c4096f68411c4a86c9276 (plain) (blame)
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use std::io::{Write, stderr};

use crate::{
    ansi_escape_codes,
    app::App,
    commands::select::{SelectCommand, SharedSelectionCommandArgs},
    storage::db::{
        insert::{Operations, video::Operation},
        video::{Priority, Video, VideoStatus},
    },
};

use anyhow::{Context, Result, bail};

pub(super) mod add;

pub(crate) async fn handle_select_cmd(
    app: &App,
    cmd: SelectCommand,
    video: &mut Video,
    line_number: Option<i64>,
    ops: &mut Operations<Operation>,
) -> Result<()> {
    let status = match cmd {
        SelectCommand::Pick { shared } => Some((VideoStatus::Pick, shared)),
        SelectCommand::Drop { shared } => Some((VideoStatus::Drop, shared)),
        SelectCommand::Watched { shared } => Some((VideoStatus::Watched, shared)),
        SelectCommand::Watch { shared } => {
            if let VideoStatus::Cached {
                cache_path,
                is_focused,
            } = &video.status
            {
                Some((
                    VideoStatus::Cached {
                        cache_path: cache_path.to_owned(),
                        is_focused: *is_focused,
                    },
                    shared,
                ))
            } else {
                Some((VideoStatus::Watch, shared))
            }
        }
        SelectCommand::Url { shared } => {
            let Some(url) = shared.url else {
                bail!("You need to provide a url to `select url ..`")
            };

            let mut firefox = std::process::Command::new("firefox");
            firefox.args(["-P", "timesinks.youtube"]);
            firefox.arg(url.as_str());
            let _handle = firefox.spawn().context("Failed to run firefox")?;
            None
        }
        SelectCommand::File { .. } | SelectCommand::Split { .. } | SelectCommand::Add { .. } => {
            unreachable!("These should have been filtered out")
        }
    };

    if let Some((status, shared)) = status {
        handle_status_change(
            app,
            video,
            shared,
            line_number,
            status,
            line_number.is_none(),
            ops,
        )
        .await?;
    }

    Ok(())
}

async fn handle_status_change(
    app: &App,
    video: &mut Video,
    shared: SharedSelectionCommandArgs,
    line_number: Option<i64>,
    new_status: VideoStatus,
    is_single: bool,
    ops: &mut Operations<Operation>,
) -> Result<()> {
    let priority = compute_priority(line_number, shared.priority);

    video.set_status(new_status, ops);
    if let Some(priority) = priority {
        video.set_priority(priority, ops);
    }

    if let Some(subtitle_langs) = shared.subtitle_langs {
        video.set_subtitle_langs(subtitle_langs, ops);
    }
    if let Some(playback_speed) = shared.playback_speed {
        video.set_playback_speed(playback_speed, ops);
    }

    if !is_single {
        ansi_escape_codes::clear_whole_line();
        ansi_escape_codes::move_to_col(1);
    }

    eprint!("{}", &video.to_line_display(app, None).await?);

    if is_single {
        eprintln!();
    } else {
        stderr().flush()?;
    }

    Ok(())
}

fn compute_priority(line_number: Option<i64>, priority: Option<i64>) -> Option<Priority> {
    if let Some(pri) = priority {
        Some(Priority::from(pri))
    } else {
        line_number.map(Priority::from)
    }
}