1use std::collections::HashSet;
4use std::path::PathBuf;
5
6use serde::{Deserialize, Serialize};
7
8use crate::types::PluginKind;
9
10#[derive(Debug, Clone)]
12pub struct PluginConfig {
13 pub plugin_dir: PathBuf,
15
16 pub config_dir: PathBuf,
18
19 pub enabled: bool,
21
22 pub default_timeout_ms: u64,
24
25 pub max_memory_mb: usize,
27
28 pub allow_network: bool,
30
31 pub disabled_plugins: HashSet<String>,
33}
34
35impl Default for PluginConfig {
36 fn default() -> Self {
37 let config_dir = dirs::config_dir()
38 .unwrap_or_else(|| PathBuf::from("."))
39 .join("gravityfile");
40
41 Self {
42 plugin_dir: config_dir.join("plugins"),
43 config_dir,
44 enabled: true,
45 default_timeout_ms: 5000,
46 max_memory_mb: 256,
47 allow_network: false,
48 disabled_plugins: HashSet::new(),
49 }
50 }
51}
52
53impl PluginConfig {
54 pub fn with_plugin_dir(mut self, dir: PathBuf) -> Self {
56 self.plugin_dir = dir;
57 self
58 }
59
60 pub fn with_timeout(mut self, timeout_ms: u64) -> Self {
62 self.default_timeout_ms = timeout_ms;
63 self
64 }
65
66 pub fn disable_plugin(mut self, name: impl Into<String>) -> Self {
68 self.disabled_plugins.insert(name.into());
69 self
70 }
71
72 pub fn is_disabled(&self, name: &str) -> bool {
74 self.disabled_plugins.contains(name)
75 }
76}
77
78#[derive(Debug, Clone, Serialize, Deserialize)]
80pub struct PluginMetadata {
81 pub name: String,
83
84 #[serde(default = "default_version")]
86 pub version: String,
87
88 #[serde(default)]
90 pub description: String,
91
92 #[serde(default)]
94 pub author: String,
95
96 #[serde(default)]
98 pub url: String,
99
100 #[serde(default = "default_runtime")]
102 pub runtime: String,
103
104 #[serde(default)]
106 pub kind: PluginKind,
107
108 #[serde(default = "default_entry")]
110 pub entry: String,
111
112 #[serde(default)]
114 pub min_version: Option<String>,
115
116 #[serde(default)]
118 pub hooks: PluginHooks,
119
120 #[serde(default)]
122 pub permissions: PluginPermissions,
123
124 #[serde(default)]
126 pub dependencies: Vec<String>,
127}
128
129fn default_version() -> String {
130 "0.1.0".to_string()
131}
132
133fn default_runtime() -> String {
134 "lua".to_string()
135}
136
137fn default_entry() -> String {
138 "main.lua".to_string()
139}
140
141impl Default for PluginMetadata {
142 fn default() -> Self {
143 Self {
144 name: String::new(),
145 version: default_version(),
146 description: String::new(),
147 author: String::new(),
148 url: String::new(),
149 runtime: default_runtime(),
150 kind: PluginKind::Hook,
151 entry: default_entry(),
152 min_version: None,
153 hooks: PluginHooks::default(),
154 permissions: PluginPermissions::default(),
155 dependencies: vec![],
156 }
157 }
158}
159
160#[derive(Debug, Clone, Default, Serialize, Deserialize)]
162pub struct PluginHooks {
163 #[serde(default)]
165 pub on_navigate: bool,
166 #[serde(default)]
167 pub on_drill_down: bool,
168 #[serde(default)]
169 pub on_back: bool,
170
171 #[serde(default)]
173 pub on_scan_start: bool,
174 #[serde(default)]
175 pub on_scan_progress: bool,
176 #[serde(default)]
177 pub on_scan_complete: bool,
178
179 #[serde(default)]
181 pub on_delete_start: bool,
182 #[serde(default)]
183 pub on_delete_complete: bool,
184 #[serde(default)]
185 pub on_copy_start: bool,
186 #[serde(default)]
187 pub on_copy_complete: bool,
188 #[serde(default)]
189 pub on_move_start: bool,
190 #[serde(default)]
191 pub on_move_complete: bool,
192
193 #[serde(default)]
195 pub on_render: bool,
196 #[serde(default)]
197 pub on_action: bool,
198 #[serde(default)]
199 pub on_mode_change: bool,
200
201 #[serde(default)]
203 pub on_startup: bool,
204 #[serde(default)]
205 pub on_shutdown: bool,
206}
207
208#[derive(Debug, Clone, Default, Serialize, Deserialize)]
210pub struct PluginPermissions {
211 #[serde(default)]
213 pub filesystem: FilesystemPermission,
214
215 #[serde(default)]
217 pub network: bool,
218
219 #[serde(default)]
221 pub commands: Vec<String>,
222
223 #[serde(default)]
225 pub env: bool,
226}
227
228#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
230#[serde(rename_all = "lowercase")]
231pub enum FilesystemPermission {
232 #[default]
234 None,
235
236 Read,
238
239 Write,
241
242 Full,
244}
245
246impl PluginPermissions {
247 pub fn can_read(&self) -> bool {
249 !matches!(self.filesystem, FilesystemPermission::None)
250 }
251
252 pub fn can_write(&self) -> bool {
254 matches!(
255 self.filesystem,
256 FilesystemPermission::Write | FilesystemPermission::Full
257 )
258 }
259
260 pub fn can_run_command(&self, cmd: &str) -> bool {
262 self.commands.iter().any(|c| c == cmd || c == "*")
263 }
264}