Skip to main content

fresh_core/
file_explorer.rs

1use crate::api::OverlayColorSpec;
2use serde::{Deserialize, Serialize};
3use std::path::PathBuf;
4use ts_rs::TS;
5
6/// Decoration metadata for a file explorer entry.
7#[derive(Debug, Clone, Serialize, Deserialize, TS)]
8#[serde(deny_unknown_fields)]
9#[ts(export)]
10pub struct FileExplorerDecoration {
11    /// File path to decorate
12    #[ts(type = "string")]
13    pub path: PathBuf,
14    /// Symbol to display (e.g., "●", "M", "A")
15    pub symbol: String,
16    /// Color as RGB array or theme key string (e.g., "ui.file_status_added_fg")
17    pub color: OverlayColorSpec,
18    /// Priority for display when multiple decorations exist (higher wins)
19    #[serde(default)]
20    pub priority: i32,
21}
22
23#[cfg(feature = "plugins")]
24impl<'js> rquickjs::FromJs<'js> for FileExplorerDecoration {
25    fn from_js(_ctx: &rquickjs::Ctx<'js>, value: rquickjs::Value<'js>) -> rquickjs::Result<Self> {
26        rquickjs_serde::from_value(value).map_err(|e| rquickjs::Error::FromJs {
27            from: "object",
28            to: "FileExplorerDecoration",
29            message: Some(e.to_string()),
30        })
31    }
32}
33
34#[cfg(all(test, feature = "plugins"))]
35mod tests {
36    use super::*;
37    use rquickjs::{Context, FromJs, Runtime, Value};
38
39    /// `FileExplorerDecoration::from_js` reads every decoration field, not
40    /// just returning a defaulted stub. Uses non-zero priority and a theme
41    /// key colour to tie down the full conversion.
42    #[test]
43    fn from_js_decodes_all_visible_fields() {
44        let rt = Runtime::new().unwrap();
45        let ctx = Context::full(&rt).unwrap();
46        ctx.with(|ctx| {
47            let v: Value = ctx
48                .eval::<Value, _>(
49                    b"({path: '/tmp/a.rs', symbol: 'M', \
50                       color: 'ui.file_status_added_fg', priority: 7})"
51                        .as_slice(),
52                )
53                .unwrap();
54            let got = FileExplorerDecoration::from_js(&ctx, v).unwrap();
55            assert_eq!(got.path, PathBuf::from("/tmp/a.rs"));
56            assert_eq!(got.symbol, "M");
57            assert_eq!(got.priority, 7);
58            assert_eq!(got.color.as_theme_key(), Some("ui.file_status_added_fg"));
59        });
60    }
61}