Skip to content

Commit 63fee43

Browse files
committed
Simplify quick view and input flow
1 parent 1fe6ee8 commit 63fee43

6 files changed

Lines changed: 54 additions & 79 deletions

File tree

src/application/ports.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@ pub trait FileSystemPort {
1515
#[allow(dead_code)]
1616
fn read_file(&self, path: &Path) -> Result<String, String>;
1717

18-
/// Checks if the given path is a file.
19-
fn is_file(&self, path: &Path) -> bool;
20-
2118
/// Checks if the given path is a directory.
2219
#[allow(dead_code)]
2320
fn is_dir(&self, path: &Path) -> bool;

src/application/use_cases/file_ops.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,6 @@ mod tests {
101101
Ok(String::new())
102102
}
103103

104-
fn is_file(&self, _path: &Path) -> bool {
105-
true
106-
}
107-
108104
fn is_dir(&self, _path: &Path) -> bool {
109105
false
110106
}

src/application/use_cases/navigate.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,6 @@ mod tests {
214214
Ok(String::new())
215215
}
216216

217-
fn is_file(&self, _path: &Path) -> bool {
218-
false
219-
}
220-
221217
fn is_dir(&self, _path: &Path) -> bool {
222218
true
223219
}

src/application/use_cases/quick_view.rs

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ use crate::application::{PanelMode, PanelState, QuickViewMode};
44
use image::{DynamicImage, load_from_memory};
55
use little_exif::exif_tag::ExifTag;
66
use little_exif::metadata::Metadata;
7-
use std::fs::{self, File};
8-
use std::io::Read;
7+
use std::fs;
98
use std::path::{Path, PathBuf};
109
use std::time::Instant;
1110

@@ -21,28 +20,14 @@ pub fn open(panel: &mut PanelState, wrap_width: u16) {
2120
}
2221

2322
pub fn scroll(panel: &mut PanelState, direction: isize, rows: u16, header: u16, footer: u16) {
24-
if let PanelMode::QuickView(QuickViewMode::Text {
25-
lines,
26-
start,
27-
length,
28-
}) = &panel.mode
29-
{
23+
if let PanelMode::QuickView(QuickViewMode::Text { start, length, .. }) = &mut panel.mode {
3024
let visible = rows.saturating_sub(header + footer) as usize;
3125
let max = length.saturating_sub(visible.max(1));
32-
let new = (*start as isize + direction).clamp(0, max as isize) as usize;
33-
panel.mode = PanelMode::QuickView(QuickViewMode::Text {
34-
lines: lines.clone(),
35-
start: new,
36-
length: *length,
37-
});
26+
*start = (*start as isize + direction).clamp(0, max as isize) as usize;
3827
}
3928
}
4029

4130
fn show_file(panel: &mut PanelState, path: PathBuf, wrap_width: u16) {
42-
if fs::metadata(&path).is_err() {
43-
panel.mode = PanelMode::QuickView(QuickViewMode::NotSupported);
44-
return;
45-
}
4631
if path.is_dir() {
4732
show_directory(panel, &path);
4833
return;
@@ -180,19 +165,14 @@ fn show_directory(panel: &mut PanelState, path: &Path) {
180165

181166
fn show_image(panel: &mut PanelState, path: &Path) {
182167
let now = Instant::now();
183-
let thumb = extract_thumbnail(path);
184-
let pixels = thumb
185-
.map(|t| t.to_rgb8())
186-
.or_else(|| image::open(path).ok().map(|i| i.to_rgb8()));
187-
let Ok(mut f) = File::open(path) else {
168+
let Ok(buf) = fs::read(path) else {
188169
panel.mode = PanelMode::QuickView(QuickViewMode::NotSupported);
189170
return;
190171
};
191-
let mut buf = Vec::new();
192-
if f.read_to_end(&mut buf).is_err() {
193-
panel.mode = PanelMode::QuickView(QuickViewMode::NotSupported);
194-
return;
195-
}
172+
let thumb = extract_thumbnail(path);
173+
let pixels = thumb
174+
.map(|t| t.to_rgb8())
175+
.or_else(|| load_from_memory(&buf).ok().map(|i| i.to_rgb8()));
196176
crate::logger::log(&format!("Image loading took: {:?}", now.elapsed()));
197177
if let Some(px) = pixels {
198178
panel.mode = PanelMode::QuickView(QuickViewMode::Image(px.into_raw(), buf));

src/infrastructure/fs_adapter.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,19 @@ impl FileSystemPort for StdFileSystem {
2828
for entry in entries.flatten() {
2929
let file_name = entry.file_name().to_string_lossy().to_string();
3030
let file_path = entry.path();
31-
let metadata = entry.metadata().ok();
3231
let is_dir = entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false);
33-
let size = metadata.as_ref().map(|m| m.len()).unwrap_or(0);
32+
let size = if is_dir {
33+
0
34+
} else {
35+
entry.metadata().map(|m| m.len()).unwrap_or(0)
36+
};
3437

3538
let kind = if is_dir {
3639
EntryKind::Dir
3740
} else {
3841
EntryKind::File
3942
};
4043

41-
// Append separator to directory names
4244
let display_name = if is_dir {
4345
format!("{}{}", file_name, std::path::MAIN_SEPARATOR)
4446
} else {
@@ -59,10 +61,6 @@ impl FileSystemPort for StdFileSystem {
5961
fs::read_to_string(path).map_err(|e| e.to_string())
6062
}
6163

62-
fn is_file(&self, path: &Path) -> bool {
63-
fs::metadata(path).map(|m| m.is_file()).unwrap_or(false)
64-
}
65-
6664
fn is_dir(&self, path: &Path) -> bool {
6765
fs::metadata(path).map(|m| m.is_dir()).unwrap_or(false)
6866
}
@@ -124,7 +122,5 @@ mod tests {
124122
let fs_adapter = StdFileSystem::new();
125123
assert!(fs_adapter.is_dir(&dir_path));
126124
assert!(!fs_adapter.is_dir(&file_path));
127-
assert!(fs_adapter.is_file(&file_path));
128-
assert!(!fs_adapter.is_file(&dir_path));
129125
}
130126
}

src/presentation/input_handler.rs

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ const FORBIDDEN_REGEX_CHARS: &[char] = &[
2727
'*', '+', '?', '|', '{', '}', '(', ')', '[', ']', '\\', '^', '$',
2828
];
2929

30+
enum QueryInputAction {
31+
None,
32+
Cancel,
33+
Submit(String),
34+
Invalid(String),
35+
}
36+
3037
pub fn is_quit(event: KeyEvent) -> bool {
3138
event.code == KeyCode::F(10)
3239
|| (event.code == KeyCode::Char('c') && event.modifiers.contains(KeyModifiers::CONTROL))
@@ -104,10 +111,10 @@ fn handle_enter(
104111
let absolute = event.modifiers.contains(KeyModifiers::SHIFT);
105112
let _ = file_ops::copy_to_clipboard(clipboard, panel, absolute);
106113
} else if !navigate::enter_selected(fs, panel)
107-
&& let Some(path) = panel.get_selected_path()
108-
&& fs.is_file(&path)
114+
&& let Some(entry) = panel.entries.get(panel.cursor)
115+
&& entry.is_file()
109116
{
110-
open.open(&path);
117+
open.open(&entry.path);
111118
}
112119
}
113120

@@ -175,19 +182,12 @@ pub fn handle_find_input(
175182
state: &mut AppState,
176183
) {
177184
if let Some(filter) = find_filter {
178-
match event.code {
179-
KeyCode::Char(c) => filter.push(c),
180-
KeyCode::Backspace => {
181-
filter.pop();
185+
match handle_query_input_event(event, filter) {
186+
QueryInputAction::None => {}
187+
QueryInputAction::Invalid(message) => {
188+
state.active_panel_mut().set_notification(message)
182189
}
183-
KeyCode::Enter => {
184-
let query = match validate_query(filter) {
185-
Ok(query) => query,
186-
Err(message) => {
187-
state.active_panel_mut().set_notification(message);
188-
return;
189-
}
190-
};
190+
QueryInputAction::Submit(query) => {
191191
let sender = sender.clone();
192192
let pane = state.active_pane;
193193
let pwd = state.active_panel().current_path.clone();
@@ -204,11 +204,10 @@ pub fn handle_find_input(
204204
});
205205
*find_filter = None;
206206
}
207-
KeyCode::Esc => {
207+
QueryInputAction::Cancel => {
208208
*find_filter = None;
209209
navigate::refresh_entries(fs, state.active_panel_mut());
210210
}
211-
_ => {}
212211
}
213212
}
214213
}
@@ -220,35 +219,46 @@ pub fn handle_ripgrep_input(
220219
state: &mut AppState,
221220
) {
222221
if let Some(f) = filter {
223-
match event.code {
224-
KeyCode::Char(c) => f.push(c),
225-
KeyCode::Backspace => {
226-
f.pop();
222+
match handle_query_input_event(event, f) {
223+
QueryInputAction::None => {}
224+
QueryInputAction::Invalid(message) => {
225+
state.active_panel_mut().set_notification(message)
227226
}
228-
KeyCode::Enter => {
229-
let query = match validate_query(f) {
230-
Ok(query) => query,
231-
Err(message) => {
232-
state.active_panel_mut().set_notification(message);
233-
return;
234-
}
235-
};
227+
QueryInputAction::Submit(query) => {
236228
let results =
237229
RipGrepAdapter::new().find(&query, &state.active_panel().current_path);
238230
let panel = state.active_panel_mut();
239231
let base = panel.current_path.clone();
240232
navigate::replace_entries_from_search(panel, results, &base);
241233
*filter = None;
242234
}
243-
KeyCode::Esc => {
235+
QueryInputAction::Cancel => {
244236
*filter = None;
245237
navigate::refresh_entries(fs, state.active_panel_mut());
246238
}
247-
_ => {}
248239
}
249240
}
250241
}
251242

243+
fn handle_query_input_event(event: KeyEvent, input: &mut String) -> QueryInputAction {
244+
match event.code {
245+
KeyCode::Char(c) => {
246+
input.push(c);
247+
QueryInputAction::None
248+
}
249+
KeyCode::Backspace => {
250+
input.pop();
251+
QueryInputAction::None
252+
}
253+
KeyCode::Enter => match validate_query(input) {
254+
Ok(query) => QueryInputAction::Submit(query),
255+
Err(message) => QueryInputAction::Invalid(message),
256+
},
257+
KeyCode::Esc => QueryInputAction::Cancel,
258+
_ => QueryInputAction::None,
259+
}
260+
}
261+
252262
fn validate_query(raw: &str) -> Result<String, String> {
253263
let query = raw.trim();
254264
if query.is_empty() {

0 commit comments

Comments
 (0)