From 052562f55dcdf9a6a9269954105208ea0423ebfe Mon Sep 17 00:00:00 2001 From: Matthew Tucciarone Date: Thu, 2 Apr 2026 18:56:56 +0700 Subject: [PATCH 1/2] fix: input issues in modals and color problems --- Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 8 ++------ src/gui/windows/about.rs | 9 +++++++- src/gui/windows/containers/itemviewer.rs | 11 ++++++++++ src/gui/windows/customizetheme.rs | 26 ++++++++++++++++++++---- src/gui/windows/mainwindow.rs | 2 ++ src/gui/windows/settings.rs | 23 +++++++++++++-------- 8 files changed, 61 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6b97b6f..d6de5e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 4 [[package]] name = "EdenExplorer" -version = "0.2.2" +version = "0.3.1" dependencies = [ "bincode", "crossbeam-channel", diff --git a/Cargo.toml b/Cargo.toml index ce75473..5da9821 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "EdenExplorer" -version = "0.2.2" +version = "0.3.1" edition = "2024" build = "src/build.rs" diff --git a/README.md b/README.md index f7e53e0..0434e79 100644 --- a/README.md +++ b/README.md @@ -285,12 +285,8 @@ - [x] **Windows environment variables PATH support** - Automatically expands Windows PATHs in breadcrumb input ### 🚀 Upcoming Features -- [ ] **Image previews using Spacebar** - GPU texture via wgpu / egui_wgpu_backend - - Decodes image once, uploads to GPU, renders instantly - - Even very large images (>10k×10k) show instantly - - Minimal CPU overhead - - Best for "popup over app" with no lag -- [ ] Drag and drop files into breadcrumb folders +- [ ] Image previews using Spacebar - GPU texture via wgpu / egui_wgpu_backend +- [ ] Drag and drop files into breadcrumb folders and directory tabs - [ ] Support network devices - [ ] Drag and drop files from EdenExplorer into Windows objects (Desktop, File Explorer, applications, etc.) diff --git a/src/gui/windows/about.rs b/src/gui/windows/about.rs index 9e20cfc..63b7a96 100644 --- a/src/gui/windows/about.rs +++ b/src/gui/windows/about.rs @@ -122,12 +122,19 @@ pub fn draw_about_window(ctx: &egui::Context, settings: &mut AboutWindow, palett ui.label("raw-window-handle"); ui.label("0.6"); ui.end_row(); + ui.label("rfd"); + ui.label("0.14"); + ui.end_row(); + ui.label("lru"); + ui.label("0.16"); + ui.end_row(); }); }); ui.add_space(8.0); ui.label("Author: Matthew Tucciarone (GitHub: mtucciarone)"); - ui.add_space(8.0); + ui.label("Repo: https://github.com/mtucciarone/EdenExplorer"); ui.label(format!("Current Version: {}", env!("CARGO_PKG_VERSION"))); + ui.label("License: MIT"); ui.separator(); // Footer ui.horizontal(|ui| { diff --git a/src/gui/windows/containers/itemviewer.rs b/src/gui/windows/containers/itemviewer.rs index fb9eaa4..e79bb37 100644 --- a/src/gui/windows/containers/itemviewer.rs +++ b/src/gui/windows/containers/itemviewer.rs @@ -11,6 +11,7 @@ use crate::gui::windows::containers::structs::{ DragState, ExplorerState, FilterState, ItemViewerFolderSizeState, ItemViewerLayout, RenameState, TabbarAction, }; +use crate::gui::windows::structs::{SettingsWindow, ThemeCustomizer}; use eframe::egui; use egui::{FontFamily, FontId}; use egui_extras::{Column, TableBuilder}; @@ -41,6 +42,8 @@ pub fn draw_item_viewer( filter_state: &mut FilterState, is_loading: bool, explorer_state: &mut ExplorerState, + theme_customizer_window: &mut ThemeCustomizer, + settings_window: &mut SettingsWindow, ) -> Option { let font_id = FontId::new(palette.text_size, FontFamily::Proportional); let mut hovered_drop_target: Option = None; @@ -130,6 +133,8 @@ pub fn draw_item_viewer( drag_state, explorer_state, is_cut_mode, + theme_customizer_window, + settings_window, ) { action = Some(global_action); } @@ -1192,6 +1197,8 @@ fn handle_global_actions( drag_state: &mut DragState, explorer_state: &mut ExplorerState, is_cut_mode: bool, + theme_customizer_window: &mut ThemeCustomizer, + settings_windows: &mut SettingsWindow, ) -> Option { let filtered_indices = &filter_state.cached_indices; let mut action: Option = None; @@ -1200,6 +1207,10 @@ fn handle_global_actions( .as_ref() .is_some_and(|t| t.is_breadcrumb_path_edit_active); + if theme_customizer_window.open || settings_windows.open { + return None; + } + // ===================================================== // 🥇 PRIORITY 1: RENAME MODE (let TextEdit own everything) // ===================================================== diff --git a/src/gui/windows/customizetheme.rs b/src/gui/windows/customizetheme.rs index 91c0cb5..a053221 100644 --- a/src/gui/windows/customizetheme.rs +++ b/src/gui/windows/customizetheme.rs @@ -4,13 +4,19 @@ use crate::gui::windows::structs::ThemeCustomizer; use eframe::egui; use egui::{FontFamily, FontId}; -fn selectable_mode(ui: &mut egui::Ui, current: ThemeMode, target: ThemeMode, label: &str) -> bool { +fn selectable_mode( + ui: &mut egui::Ui, + palette: &ThemePalette, + current: ThemeMode, + target: ThemeMode, + label: &str, +) -> bool { let selected = current == target; ui.selectable_label( selected, egui::RichText::new(label).color(if selected { - egui::Color32::WHITE + palette.tab_text_normal } else { ui.visuals().text_color() }), @@ -99,11 +105,23 @@ pub fn draw_theme_customizer( .color(label_color), ); - if selectable_mode(ui, customizer.selected_mode, ThemeMode::Dark, "Dark") { + if selectable_mode( + ui, + palette, + customizer.selected_mode, + ThemeMode::Dark, + "Dark", + ) { customizer.selected_mode = ThemeMode::Dark; } - if selectable_mode(ui, customizer.selected_mode, ThemeMode::Light, "Light") { + if selectable_mode( + ui, + palette, + customizer.selected_mode, + ThemeMode::Light, + "Light", + ) { customizer.selected_mode = ThemeMode::Light; } }); diff --git a/src/gui/windows/mainwindow.rs b/src/gui/windows/mainwindow.rs index 13ac1da..3a1970b 100644 --- a/src/gui/windows/mainwindow.rs +++ b/src/gui/windows/mainwindow.rs @@ -459,6 +459,8 @@ impl eframe::App for MainWindow { &mut self.item_viewer_filter_state, self.is_loading, &mut self.explorer_state, + &mut self.theme_customizer, + &mut self.settings_window, ); ui.add_space(16.0); diff --git a/src/gui/windows/settings.rs b/src/gui/windows/settings.rs index 2acab45..cac897d 100644 --- a/src/gui/windows/settings.rs +++ b/src/gui/windows/settings.rs @@ -1,8 +1,9 @@ use crate::core::{fs::MY_PC_PATH, indexer::WindowSizeMode}; -use crate::gui::theme::ThemePalette; +use crate::gui::theme::{ThemePalette, apply_checkbox_colors}; use crate::gui::windows::enums::SettingsAction; use crate::gui::windows::structs::{AppSettings, SettingsWindow}; use eframe::egui; +use egui::RichText; use egui_phosphor::regular; use std::path::PathBuf; @@ -101,14 +102,17 @@ pub fn draw_settings_window( }); // Folder Scanning ui.horizontal(|ui| { - if ui.checkbox( - &mut settings.current_settings.folder_scanning_enabled, - "Enable folder size scanning" - ).changed() { - // Auto-save when setting changes - action = Some(SettingsAction::ApplySettings); - } - info_icon(ui, "When enabled, the application will scan folders to calculate their sizes. This may impact performance on large directories.", palette); + ui.scope(|ui| { + apply_checkbox_colors(ui, palette, false); + if ui.checkbox( + &mut settings.current_settings.folder_scanning_enabled, + RichText::new("Enable folder size scanning").color(palette.tab_text_normal) + ).changed() { + // Auto-save when setting changes + action = Some(SettingsAction::ApplySettings); + } + }); + info_icon(ui, "When enabled, the application will scan folders to calculate their sizes. This may impact performance on large directories.", palette); }); ui.add_space(8.0); // Starting Path @@ -200,6 +204,7 @@ pub fn draw_settings_window( } info_icon(ui, "Configure the window size when the application launches.", palette); }); + ui.label("Changes are applied after restarting"); } ui.add_space(8.0); // Favorites Reset From 31d6c3a60c2240305a47d64e424e64ca6697dd12 Mon Sep 17 00:00:00 2001 From: Matthew Tucciarone Date: Thu, 2 Apr 2026 19:05:21 +0700 Subject: [PATCH 2/2] feat: auto-save theme change globally --- src/core/indexer.rs | 9 ++++++++- src/gui/windows/mainwindow.rs | 8 ++++++-- src/gui/windows/mainwindow_imp.rs | 19 ++++++++++++++++++- src/main.rs | 3 ++- 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/core/indexer.rs b/src/core/indexer.rs index 957c2e7..bf99447 100644 --- a/src/core/indexer.rs +++ b/src/core/indexer.rs @@ -13,6 +13,7 @@ struct AppSettingsSnapshot { folder_scanning_enabled: bool, window_size_mode: WindowSizeMode, pub start_path: Option, + theme: Option, } #[derive(Serialize, Deserialize)] @@ -85,7 +86,7 @@ pub fn save_favorites(drive: char, favorites: &[String]) { } } -pub fn load_app_settings() -> (bool, WindowSizeMode, PathBuf) { +pub fn load_app_settings() -> (bool, WindowSizeMode, PathBuf, Option) { let default_path = PathBuf::from(MY_PC_PATH); let path = match settings_cache_path() { Some(path) => path, @@ -97,6 +98,7 @@ pub fn load_app_settings() -> (bool, WindowSizeMode, PathBuf) { height: 800.0, }, default_path, + None, ); } }; @@ -110,6 +112,7 @@ pub fn load_app_settings() -> (bool, WindowSizeMode, PathBuf) { height: 800.0, }, default_path, + None, ); } }; @@ -118,6 +121,7 @@ pub fn load_app_settings() -> (bool, WindowSizeMode, PathBuf) { snapshot.folder_scanning_enabled, snapshot.window_size_mode, snapshot.start_path.unwrap_or(default_path), + snapshot.theme, ), Err(_) => ( true, @@ -126,6 +130,7 @@ pub fn load_app_settings() -> (bool, WindowSizeMode, PathBuf) { height: 800.0, }, default_path, + None, ), } } @@ -134,6 +139,7 @@ pub fn save_app_settings( folder_scanning_enabled: bool, window_size_mode: &WindowSizeMode, start_path: &Option, + theme: Option<&str>, ) { let path = match settings_cache_path() { Some(path) => path, @@ -144,6 +150,7 @@ pub fn save_app_settings( folder_scanning_enabled, window_size_mode: window_size_mode.clone(), start_path: start_path.clone(), + theme: theme.map(|s| s.to_string()), }; if let Ok(data) = bincode::serialize(&snapshot) { let _ = std::fs::write(path, data); diff --git a/src/gui/windows/mainwindow.rs b/src/gui/windows/mainwindow.rs index 3a1970b..647e3f6 100644 --- a/src/gui/windows/mainwindow.rs +++ b/src/gui/windows/mainwindow.rs @@ -86,7 +86,8 @@ pub struct MainWindow { impl Default for MainWindow { fn default() -> Self { // Load saved settings - let (folder_scanning_enabled, window_size_mode, start_path) = load_app_settings(); + let (folder_scanning_enabled, window_size_mode, start_path, saved_theme) = + load_app_settings(); let loaded_settings = AppSettings { folder_scanning_enabled, window_size_mode: window_size_mode.clone(), @@ -116,7 +117,10 @@ impl Default for MainWindow { rename_state: None, pending_size_queue: VecDeque::new(), pending_size_set: HashSet::new(), - theme: ThemeMode::Dark, + theme: match saved_theme.as_deref() { + Some("light") => ThemeMode::Light, + Some("dark") | _ => ThemeMode::Dark, + }, theme_dirty: true, window_override_set: false, drag_state: DragState::default(), diff --git a/src/gui/windows/mainwindow_imp.rs b/src/gui/windows/mainwindow_imp.rs index e9a50fc..3815090 100644 --- a/src/gui/windows/mainwindow_imp.rs +++ b/src/gui/windows/mainwindow_imp.rs @@ -535,6 +535,10 @@ impl MainWindow { .folder_scanning_enabled, &self.settings_window.current_settings.window_size_mode, &self.settings_window.current_settings.start_path, + Some(match self.theme { + crate::gui::theme::ThemeMode::Dark => "dark", + crate::gui::theme::ThemeMode::Light => "light", + }), ); } SettingsAction::ResetToDefaults => { @@ -646,7 +650,7 @@ impl MainWindow { self.load_path(); } } else { - let (_folder_scanning_enabled, _window_size_mode, start_path) = + let (_folder_scanning_enabled, _window_size_mode, start_path, _saved_theme) = load_app_settings(); self.tabs[0].nav = Navigation::new(start_path); self.active_tab = 0; @@ -705,6 +709,19 @@ impl MainWindow { ThemeMode::Light => ThemeMode::Dark, }; self.theme_dirty = true; + + // Save the theme setting + save_app_settings( + self.settings_window + .current_settings + .folder_scanning_enabled, + &self.settings_window.current_settings.window_size_mode, + &self.settings_window.current_settings.start_path, + Some(match self.theme { + ThemeMode::Dark => "dark", + ThemeMode::Light => "light", + }), + ); } if action.customize_theme { diff --git a/src/main.rs b/src/main.rs index faba0ba..ff5701a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,8 @@ fn main() -> eframe::Result<()> { CoInitializeEx(None, COINIT_APARTMENTTHREADED).unwrap(); } let icon = load_icon().expect("Failed to load icon"); - let (_folder_scanning_enabled, window_size_mode, _start_path) = load_app_settings(); + let (_folder_scanning_enabled, window_size_mode, _start_path, _saved_theme) = + load_app_settings(); let window_size = match window_size_mode { WindowSizeMode::FullScreen => egui::Vec2::new(1920.0, 1080.0), WindowSizeMode::HalfScreen => egui::Vec2::new(960.0, 540.0),