Skip to content

Commit 665b766

Browse files
committed
refactor: apply settings page, logging behavior,
error handling, and updated dependencies
1 parent f0ed7f5 commit 665b766

20 files changed

+748
-629
lines changed

src/app/actions.rs

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,26 @@ use serde::{Deserialize, Serialize};
22
use std::path::PathBuf;
33

44
use crate::{
5-
app::{AppContext, AppState},
5+
app::{AppContext, AppState, config::AppConfig},
66
file_handling::{
7-
metadata::{DirMetadata, FileMetadata},
87
Explorer, SearchResult,
8+
metadata::{DirMetadata, FileMetadata},
99
},
10-
ui::{search_widget::SearchMode, Theme},
10+
ui::{Theme, search_widget::SearchMode},
1111
};
1212

1313
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1414
/// Enum that tracks all the actions that can be carried out by the App
1515
pub enum Action {
16+
ApplyAppSettings(AppConfig),
17+
ApplySettingsInput,
18+
CloseMetadata,
19+
DropDownClosed,
20+
DropDownShowing,
1621
Error(String),
1722
ExportDone,
1823
ExportFailure(String),
24+
ForcedShutdown,
1925
HideOrShowSystemOverview,
2026
Init,
2127
LoadDir(PathBuf, bool),
@@ -27,20 +33,58 @@ pub enum Action {
2733
Render,
2834
Resize(u16, u16),
2935
Resume,
36+
SettingsInputCanceled,
37+
SettingsInputShowing,
3038
SearchDone(Option<SearchResult>),
3139
SetCommandDescription(Option<String>),
3240
ShowAbout(AppContext),
3341
ShowDirMetadata(DirMetadata),
3442
ShowFileMetadata(PathBuf, FileMetadata),
3543
ShowHelp(AppContext),
36-
CloseMetadata,
3744
ShowResultsPage(SearchResult, SearchMode),
3845
ShowSearchPage(PathBuf),
46+
ShowSettings(AppContext),
3947
StartSearch(PathBuf, String, usize, bool),
4048
Suspend,
4149
SwitchAppContext(AppContext),
4250
Tick,
43-
ForcedShutdown,
4451
ToggleTheme(Theme),
4552
UpdateAppState(AppState),
4653
}
54+
55+
// pub enum Action {
56+
// DropDownShowing,
57+
// DropDownClosed,
58+
// Error(String),
59+
// ExportDone,
60+
// ExportFailure(String),
61+
// HideOrShowSystemOverview,
62+
// Init,
63+
// LoadDir(PathBuf, bool),
64+
// LoadDirDone(Explorer),
65+
// LoadDirMetadata(String, PathBuf, bool),
66+
// LoadDirMetadataDone(Option<DirMetadata>),
67+
// None,
68+
// Quit,
69+
// Render,
70+
// Resize(u16, u16),
71+
// Resume,
72+
// SearchDone(Option<SearchResult>),
73+
// SetCommandDescription(Option<String>),
74+
// ShowAbout(AppContext),
75+
// ShowDirMetadata(DirMetadata),
76+
// ShowFileMetadata(PathBuf, FileMetadata),
77+
// ShowHelp(AppContext),
78+
// CloseMetadata,
79+
// ShowResultsPage(SearchResult, SearchMode),
80+
// ShowSearchPage(PathBuf),
81+
// ShowSettings(AppContext),
82+
// ApplySettings(AppConfig),
83+
// StartSearch(PathBuf, String, usize, bool),
84+
// Suspend,
85+
// SwitchAppContext(AppContext),
86+
// Tick,
87+
// ForcedShutdown,
88+
// ToggleTheme(Theme),
89+
// UpdateAppState(AppState),
90+
// }

src/app/config.rs

Lines changed: 158 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,218 @@
1+
use anyhow::Result;
12
use serde::{Deserialize, Serialize};
23
use std::path::{Path, PathBuf};
34

4-
use crate::{ui::Theme, utils};
5+
use crate::{
6+
ui::Theme,
7+
utils::{absolute_path_as_string, data_dir, format_path_for_display, user_home_dir},
8+
};
59

610
pub const CONFIG_NAME: &str = "config.toml";
711

8-
#[derive(Debug, Clone, Serialize, Deserialize)]
12+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
913
pub struct AppConfig {
10-
/// Define the app theme [Light, Dark, Dracula, Indigo]
11-
theme: Theme,
14+
/// The default app theme on start up [Light, Dark, Dracula, Indigo]
15+
default_theme: Theme,
1216
/// Directory in which the Explorer should start
1317
start_dir: PathBuf,
1418
/// Directory to which the search results are to be exported
1519
export_dir: PathBuf,
1620
/// Enable/Disable following symbolic links
1721
follow_sym_links: bool,
22+
/// Update Rate per second for the System-Overview
23+
system_update_rate: u8,
24+
/// Frames per Second (Rendering)
25+
fps: u8,
1826
}
1927

2028
impl Default for AppConfig {
2129
fn default() -> Self {
2230
Self {
23-
theme: Default::default(),
24-
start_dir: utils::user_home_dir().map_or(
31+
default_theme: Default::default(),
32+
start_dir: user_home_dir().map_or(
2533
{
2634
std::env::current_dir()
2735
.ok()
2836
.unwrap_or(PathBuf::new().join("."))
2937
},
3038
|home_dir| home_dir,
3139
),
32-
export_dir: utils::data_dir(),
40+
export_dir: data_dir(),
3341
follow_sym_links: false,
42+
system_update_rate: 1,
43+
fps: 45,
3444
}
3545
}
3646
}
3747

3848
impl AppConfig {
39-
fn ignore_given_init_dir(&mut self) {
40-
self.start_dir = utils::user_home_dir().map_or(
41-
{
42-
std::env::current_dir()
43-
.ok()
44-
.unwrap_or(PathBuf::new().join("."))
45-
},
46-
|home_dir| home_dir,
47-
);
48-
}
49-
50-
fn ignore_given_export_dir(&mut self) {
51-
self.export_dir = utils::data_dir();
52-
}
53-
5449
pub fn load_config<P: AsRef<Path>>(p: P) -> AppConfig {
5550
let config_file = p.as_ref();
5651

5752
if !config_file.exists() {
5853
let config = AppConfig::default();
5954
// If no config found, try to store a new config file at start up
60-
if let Err(config_err) = confy::store_path(config_file, config.clone()) {
55+
if let Err(err) = confy::store_path(config_file, config.clone()) {
6156
log::error!(
62-
"Failed to store a new configuration file at '{}'",
63-
utils::absolute_path_as_string(config_file)
57+
"Failed to store a new configuration file at [{}]",
58+
absolute_path_as_string(config_file)
6459
);
65-
log::error!("Config error: {:#?}", config_err);
66-
log::error!("Fallback to the default configuration");
60+
AppConfig::log_confy_err(err);
6761
}
6862
config
6963
} else {
7064
// Try to load the given configuration file
7165
match confy::load_path::<AppConfig>(config_file) {
7266
Ok(config) => config.validate_config(),
73-
Err(config_err) => {
67+
Err(err) => {
7468
log::error!(
75-
"Failed to load configuration file '{}'",
76-
utils::absolute_path_as_string(config_file)
69+
"Failed to load configuration file [{}]",
70+
absolute_path_as_string(config_file)
7771
);
78-
log::error!("Config error: {:#?}", config_err);
79-
log::error!("Fallback to the default configuration");
72+
AppConfig::log_confy_err(err);
8073
AppConfig::default()
8174
}
8275
}
8376
}
8477
}
8578

79+
fn log_confy_err<T: std::error::Error>(err: T) {
80+
log::error!("{:#?}", err);
81+
log::warn!("Fallback to the default configuration");
82+
}
83+
84+
pub fn save_config<P: AsRef<Path>>(&self, p: P) -> Result<()> {
85+
confy::store_path(p.as_ref(), self)?;
86+
Ok(())
87+
}
88+
8689
fn validate_config(self) -> Self {
8790
let mut config = self.clone();
8891

89-
if !self.start_dir.is_dir() {
90-
log::error!("Invalid path found for config option 'start_dir' -> path will be ignored, fallback to default");
91-
config.ignore_given_init_dir();
92+
if !config.start_dir.is_dir() {
93+
let start_dir = user_home_dir().map_or(
94+
{
95+
std::env::current_dir()
96+
.ok()
97+
.unwrap_or(PathBuf::new().join("."))
98+
},
99+
|home_dir| home_dir,
100+
);
101+
log::warn!(
102+
"[Config] Invalid path for option 'start_dir' -> No such directory, fallback to default [{}]",
103+
absolute_path_as_string(&start_dir)
104+
);
105+
106+
config.start_dir = start_dir;
107+
}
108+
109+
if !config.export_dir.is_dir() {
110+
let export_dir = data_dir();
111+
log::warn!(
112+
"[Config] Invalid path for option 'export_dir' -> No such directory, fallback to default [{}]",
113+
absolute_path_as_string(&export_dir)
114+
);
115+
config.export_dir = export_dir;
116+
}
117+
118+
if config.fps > 60 {
119+
let default_fps: u8 = 45;
120+
log::warn!(
121+
"[Config] Invalid value for option 'fps' -> It cannot be greater than 60, fallback to default [{}]",
122+
default_fps
123+
);
124+
config.fps = default_fps;
92125
}
93126

94-
if !self.export_dir.is_dir() {
95-
log::error!(
96-
"Invalid path found for config option 'export_dir' -> path will be ignored, fallback to default"
127+
if config.system_update_rate > 5 {
128+
let default_update_rate: u8 = 1;
129+
log::warn!(
130+
"[Config] Invalid value for option 'system_update_rate' -> It cannot be greater than 5, fallback to default [{}]",
131+
default_update_rate
97132
);
98-
config.ignore_given_export_dir();
133+
config.system_update_rate = default_update_rate;
99134
}
100135

101136
config
102137
}
103138

139+
pub fn config_docs(&self, with_description: bool) -> Vec<Vec<String>> {
140+
let start_dir = format_path_for_display(absolute_path_as_string(self.start_dir()));
141+
let export_dir = format_path_for_display(absolute_path_as_string(self.export_dir()));
142+
let follow_sym_links = if self.follow_sym_links() { "Yes" } else { "No" };
143+
let fps = format!("{} / sec", self.fps());
144+
let update_rate = format!("{} / sec", self.system_update_rate());
145+
146+
let rows = vec![
147+
(
148+
"Default theme",
149+
self.theme().to_string(),
150+
"App theme at startup",
151+
),
152+
(
153+
"Start directory",
154+
start_dir,
155+
"Explorer directory at startup",
156+
),
157+
(
158+
"Export directory",
159+
export_dir,
160+
"Directory to which the search results are exported",
161+
),
162+
(
163+
"Follow symbolic links",
164+
follow_sym_links.to_string(),
165+
"Defines whether Explorer follows symbolic links",
166+
),
167+
(
168+
"Frames per second (render)",
169+
fps,
170+
"Frames per second (TUI render)",
171+
),
172+
(
173+
"Update rate (System-Resources)",
174+
update_rate,
175+
"Update rate of system resource usage per second",
176+
),
177+
];
178+
179+
rows.into_iter()
180+
.map(|(key, value, desc)| {
181+
if with_description {
182+
vec![key.into(), value, desc.into()]
183+
} else {
184+
vec![key.into(), value]
185+
}
186+
})
187+
.collect()
188+
}
189+
190+
pub fn set_theme(&mut self, t: Theme) {
191+
self.default_theme = t;
192+
}
193+
194+
pub fn set_start_dir<P: AsRef<Path>>(&mut self, p: P) {
195+
self.start_dir = p.as_ref().to_path_buf();
196+
}
197+
198+
pub fn set_export_dir<P: AsRef<Path>>(&mut self, p: P) {
199+
self.export_dir = p.as_ref().to_path_buf();
200+
}
201+
202+
pub fn set_follow_sym_links(&mut self, yes: bool) {
203+
self.follow_sym_links = yes;
204+
}
205+
206+
pub fn set_system_update_rate(&mut self, rate: u8) {
207+
self.system_update_rate = rate;
208+
}
209+
210+
pub fn set_fps(&mut self, fps: u8) {
211+
self.fps = fps;
212+
}
213+
104214
pub fn theme(&self) -> Theme {
105-
self.theme
215+
self.default_theme
106216
}
107217

108218
pub fn start_dir(&self) -> PathBuf {
@@ -116,4 +226,12 @@ impl AppConfig {
116226
pub fn follow_sym_links(&self) -> bool {
117227
self.follow_sym_links
118228
}
229+
230+
pub fn system_update_rate(&self) -> u8 {
231+
self.system_update_rate
232+
}
233+
234+
pub fn fps(&self) -> u8 {
235+
self.fps
236+
}
119237
}

0 commit comments

Comments
 (0)