cosmic_files/
context_action.rs

1// SPDX-License-Identifier: GPL-3.0-only
2
3use std::path::PathBuf;
4
5use serde::{Deserialize, Serialize};
6
7use crate::mime_app;
8use crate::spawn_detached::spawn_detached;
9
10#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
11pub enum ContextActionSelection {
12    #[default]
13    #[serde(alias = "any")]
14    Any,
15    #[serde(alias = "files")]
16    Files,
17    #[serde(alias = "folders")]
18    Folders,
19}
20
21#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
22#[serde(default)]
23pub struct ContextActionPreset {
24    pub name: String,
25    pub confirm: bool,
26    pub selection: ContextActionSelection,
27    pub steps: Vec<String>,
28}
29
30impl ContextActionPreset {
31    pub fn matches_selection(&self, selected: usize, selected_dir: usize) -> bool {
32        if selected == 0 {
33            return false;
34        }
35
36        match self.selection {
37            ContextActionSelection::Any => true,
38            ContextActionSelection::Files => selected_dir == 0,
39            ContextActionSelection::Folders => selected_dir == selected,
40        }
41    }
42
43    pub fn run(&self, paths: &[PathBuf]) {
44        if self.steps.is_empty() {
45            log::warn!("context action {:?} has no steps", self.name);
46            return;
47        }
48
49        for step in &self.steps {
50            let Some(commands) = mime_app::exec_to_command(step, &self.name, None, paths) else {
51                log::warn!(
52                    "failed to parse context action {:?}: invalid Exec {:?}",
53                    self.name,
54                    step
55                );
56                return;
57            };
58
59            for mut command in commands {
60                if let Err(err) = spawn_detached(&mut command) {
61                    log::warn!(
62                        "failed to run context action {:?} step {:?}: {}",
63                        self.name,
64                        step,
65                        err
66                    );
67                    return;
68                }
69            }
70        }
71    }
72}
73
74pub fn run(actions: &[ContextActionPreset], action: usize, paths: &[PathBuf]) {
75    if let Some(preset) = actions.get(action) {
76        preset.run(paths);
77    } else {
78        log::warn!("invalid context action index `{action}`");
79    }
80}