par_term_settings_ui/lib.rs
1//! Settings UI for par-term terminal emulator.
2//!
3//! This crate provides an egui-based settings interface for configuring
4//! terminal options at runtime. It is designed to be decoupled from the
5//! main terminal implementation through trait interfaces.
6//!
7//! # ARC-010 — Crate Size Note
8//!
9//! This crate is ~28,644 lines across ~100 files, making it the largest sub-crate
10//! and a compile-time bottleneck. Planned decomposition (deferred — multi-sprint effort):
11//!
12//! 1. Extract shader editor sub-crate (~5K lines): `par-term-shader-ui`
13//! - shader_editor, shader_dialogs, shader_utils, cursor_shader_editor
14//! - background_tab/shader_settings, background_tab/shader_channel_settings
15//!
16//! 2. Extract automation UI sub-crate (~3K lines): `par-term-automation-ui`
17//! - automation_tab/*, scripts_tab/*
18//!
19//! Tracking: Issue ARC-010 in AUDIT.md.
20
21use par_term_config::{Config, Profile, ProfileId};
22
23/// Callback type for detecting modified bundled shaders.
24pub type ShaderDetectModifiedFn = fn() -> Result<Vec<String>, String>;
25
26/// Callback type for running shader lint/readability analysis from Settings.
27pub type ShaderLintFn = fn(&std::path::Path, Option<f32>, Option<f32>) -> Result<String, String>;
28
29// Trait interfaces for decoupling from main crate
30mod traits;
31pub use traits::*;
32
33// Window arrangements (pure data types)
34pub mod arrangements;
35pub use arrangements::{
36 ArrangementId, ArrangementManager, MonitorInfo, TabSnapshot, WindowArrangement, WindowSnapshot,
37};
38
39// Shell detection utility
40pub mod shell_detection;
41
42// Profile management modal UI
43pub mod profile_modal_ui;
44pub use profile_modal_ui::{ProfileModalAction, ProfileModalUI};
45
46// Nerd Font integration (font loading + icon presets)
47pub mod nerd_font;
48
49// Reorganized settings tabs
50pub mod actions_tab;
51pub mod advanced_tab;
52pub mod ai_inspector_tab;
53pub mod appearance_tab;
54pub mod automation_tab;
55pub mod effects_tab;
56pub mod input_tab;
57pub mod integrations_tab;
58pub mod notifications_tab;
59pub mod profiles_tab;
60pub mod quick_settings;
61pub mod scripts_tab;
62pub mod search_keywords;
63pub mod section;
64pub mod sidebar;
65pub mod snippets_tab;
66pub mod ssh_tab;
67pub mod status_bar_tab;
68pub mod terminal_tab;
69pub mod window_tab;
70
71// Internal implementation modules (no longer exposed as standalone tabs)
72mod arrangements_tab;
73pub use arrangements_tab::ArrangementsTabState;
74mod badge_tab;
75mod progress_bar_tab;
76
77// Background tab is still needed by effects_tab for delegation
78pub mod background_tab;
79
80// Shader editor components (used by background_tab)
81mod cursor_shader_editor;
82mod shader_dialogs;
83mod shader_editor;
84mod shader_utils;
85
86// SettingsUI struct and impl
87mod settings_ui;
88pub use settings_ui::SettingsUI;
89
90pub use sidebar::SettingsTab;
91
92// Re-export types that settings consumers need
93pub use par_term_config::{
94 self as config, BackgroundImageMode as BgMode, CursorShaderMetadataCache as CursorShaderCache,
95 ProfileManager, ProfileSource, ShaderMetadataCache as ShaderCache, Theme, VsyncMode,
96};
97
98/// Result of shader editor actions
99#[derive(Debug, Clone)]
100pub struct ShaderEditorResult {
101 /// New shader source code to compile and apply
102 pub source: String,
103}
104
105/// Result of cursor shader editor actions
106#[derive(Debug, Clone)]
107pub struct CursorShaderEditorResult {
108 /// New cursor shader source code to compile and apply
109 pub source: String,
110}
111
112/// Result of processing a settings window event.
113///
114/// This enum bridges the settings UI crate with the main application.
115/// The main application processes these actions after events are handled
116/// by the settings window.
117#[derive(Debug, Clone)]
118pub enum SettingsWindowAction {
119 /// No action needed
120 None,
121 /// Close the settings window
122 Close,
123 /// Apply config changes to terminal windows (live update)
124 ApplyConfig(Config),
125 /// Save config to disk
126 SaveConfig(Config),
127 /// Apply background shader from editor
128 ApplyShader(ShaderEditorResult),
129 /// Apply cursor shader from editor
130 ApplyCursorShader(CursorShaderEditorResult),
131 /// Send a test notification to verify permissions
132 TestNotification,
133 /// Save profiles from inline editor to all windows
134 SaveProfiles(Vec<Profile>),
135 /// Open a profile in the focused terminal window
136 OpenProfile(ProfileId),
137 /// Start a coprocess by config index on the active tab
138 StartCoprocess(usize),
139 /// Stop a coprocess by config index on the active tab
140 StopCoprocess(usize),
141 /// Start a script by config index on the active tab
142 StartScript(usize),
143 /// Stop a script by config index on the active tab
144 StopScript(usize),
145 /// Open the debug log file in the system's default editor/viewer
146 OpenLogFile,
147 /// Save the current window layout as an arrangement
148 SaveArrangement(String),
149 /// Restore a saved window arrangement
150 RestoreArrangement(ArrangementId),
151 /// Delete a saved window arrangement
152 DeleteArrangement(ArrangementId),
153 /// Rename a saved window arrangement
154 RenameArrangement(ArrangementId, String),
155 /// Move a saved window arrangement one position up in the list
156 MoveArrangementUp(ArrangementId),
157 /// Move a saved window arrangement one position down in the list
158 MoveArrangementDown(ArrangementId),
159 /// Replace a saved window arrangement with the current window layout
160 ReplaceArrangement(ArrangementId),
161 /// User requested an immediate update check
162 ForceUpdateCheck,
163 /// User requested to install the available update
164 InstallUpdate(String),
165 /// Flash pane indices on the terminal window
166 IdentifyPanes,
167 /// Install shell integration for the detected shell
168 InstallShellIntegration,
169 /// Uninstall shell integration from all shells
170 UninstallShellIntegration,
171 /// Assistant prompt library changed; terminal windows should reload prompt menus
172 AssistantPromptsChanged,
173}
174
175/// Lightweight information about a saved arrangement (used by trait interface).
176#[derive(Debug, Clone)]
177pub struct ArrangementInfo {
178 /// Unique identifier
179 pub id: ArrangementId,
180 /// Display name
181 pub name: String,
182 /// Number of windows in the arrangement
183 pub window_count: usize,
184}
185
186/// Result of a shader installation operation.
187#[derive(Debug, Clone)]
188pub struct ShaderInstallResult {
189 /// Number of shaders installed
190 pub installed: usize,
191 /// Number of shaders skipped (unchanged)
192 pub skipped: usize,
193 /// Number of obsolete shaders removed
194 pub removed: usize,
195}
196
197/// Result of a shader uninstallation operation.
198#[derive(Debug, Clone)]
199pub struct ShaderUninstallResult {
200 /// Number of shaders removed
201 pub removed: usize,
202 /// Number of modified shaders kept
203 pub kept: usize,
204 /// Whether confirmation is needed for modified files
205 pub needs_confirmation: bool,
206}
207
208/// Result of shell integration installation.
209#[derive(Debug, Clone)]
210pub struct ShellIntegrationInstallResult {
211 /// Shell type that was configured
212 pub shell: String,
213 /// Path to the integration script
214 pub script_path: String,
215 /// RC file that was modified
216 pub rc_file: String,
217 /// Whether a shell restart is needed
218 pub needs_restart: bool,
219}
220
221/// Result of shell integration uninstallation.
222#[derive(Debug, Clone)]
223pub struct ShellIntegrationUninstallResult {
224 /// Whether rc files were cleaned
225 pub cleaned: bool,
226 /// Whether manual intervention is needed
227 pub needs_manual: bool,
228 /// Number of integration scripts removed
229 pub scripts_removed: usize,
230}
231
232/// Result of a self-update operation.
233#[derive(Debug, Clone)]
234pub struct UpdateResult {
235 /// Old version before the update
236 pub old_version: String,
237 /// New version after the update
238 pub new_version: String,
239 /// Path where the binary was installed
240 pub install_path: String,
241 /// Whether a restart is needed
242 pub needs_restart: bool,
243}
244
245/// Installation type detected for the running binary.
246#[derive(Debug, Clone, Copy, PartialEq, Eq)]
247pub enum InstallationType {
248 /// Installed via Homebrew
249 Homebrew,
250 /// Installed via `cargo install`
251 CargoInstall,
252 /// Running from a macOS .app bundle
253 MacOSBundle,
254 /// Standalone binary
255 StandaloneBinary,
256}
257
258/// Result of an update check.
259#[derive(Debug, Clone)]
260pub enum UpdateCheckResult {
261 /// No update available, up to date
262 UpToDate,
263 /// An update is available
264 UpdateAvailable(UpdateCheckInfo),
265 /// Update checking is disabled
266 Disabled,
267 /// Check was skipped (cooldown not elapsed)
268 Skipped,
269 /// Error occurred during check
270 Error(String),
271}
272
273/// Information about an available update.
274#[derive(Debug, Clone)]
275pub struct UpdateCheckInfo {
276 /// Version string (e.g., "0.16.0")
277 pub version: String,
278 /// Release notes/changelog
279 pub release_notes: Option<String>,
280 /// URL to release page
281 pub release_url: String,
282 /// When the release was published
283 pub published_at: Option<String>,
284}
285
286/// Format a timestamp string for display in the UI.
287pub fn format_timestamp(timestamp: &str) -> String {
288 match chrono::DateTime::parse_from_rfc3339(timestamp) {
289 Ok(dt) => dt.format("%Y-%m-%d %H:%M").to_string(),
290 Err(_) => timestamp.to_string(),
291 }
292}
293
294/// Get the path to the debug log file.
295///
296/// Must stay in sync with the writer in the root crate (`src/debug.rs`), which
297/// resolves the same `std::env::temp_dir()` location — `$TMPDIR` on macOS
298/// (a `/var/folders/…` path), `/tmp` on Linux, `%TEMP%` on Windows.
299pub fn log_path() -> std::path::PathBuf {
300 std::env::temp_dir().join("par_term_debug.log")
301}