runa_tui/app/
preview.rs

1use crate::file_manager::FileEntry;
2use std::path::PathBuf;
3use std::time::Instant;
4
5pub enum PreviewData {
6    Directory(Vec<FileEntry>),
7    File(Vec<String>),
8    Empty,
9}
10
11pub struct PreviewState {
12    data: PreviewData,
13    selected_idx: usize,
14    current_path: Option<PathBuf>,
15    request_id: u64,
16    pending: bool,
17    last_input_time: Instant,
18}
19
20impl PreviewState {
21    // Getters/ Accessors
22    pub fn data(&self) -> &PreviewData {
23        &self.data
24    }
25
26    pub fn selected_idx(&self) -> usize {
27        self.selected_idx
28    }
29
30    pub fn request_id(&self) -> u64 {
31        self.request_id
32    }
33
34    // Setters / mutators
35    pub fn set_selected_idx(&mut self, idx: usize) {
36        let len = match &self.data {
37            PreviewData::Directory(entries) => entries.len(),
38            PreviewData::File(lines) => lines.len(),
39            PreviewData::Empty => 0,
40        };
41        self.selected_idx = idx.min(len.saturating_sub(1));
42    }
43
44    pub fn mark_pending(&mut self) {
45        self.pending = true;
46        self.last_input_time = Instant::now();
47    }
48
49    // Debounce timing for preview render
50    pub fn should_trigger(&self) -> bool {
51        self.pending && self.last_input_time.elapsed().as_millis() > 75
52    }
53
54    pub fn prepare_new_request(&mut self, path: PathBuf) -> u64 {
55        self.request_id += 1;
56        self.current_path = Some(path);
57        self.pending = false;
58        self.request_id
59    }
60
61    pub fn update_content(&mut self, lines: Vec<String>, request_id: u64) {
62        if request_id == self.request_id {
63            self.data = PreviewData::File(lines);
64        }
65    }
66
67    pub fn update_from_entries(&mut self, entries: Vec<FileEntry>, request_id: u64) {
68        if request_id == self.request_id {
69            self.data = PreviewData::Directory(entries);
70            self.selected_idx = 0;
71        }
72    }
73
74    pub fn set_error(&mut self, err: String) {
75        self.data = PreviewData::File(vec![err]);
76    }
77}
78
79impl PreviewData {
80    pub fn is_empty(&self) -> bool {
81        match self {
82            PreviewData::Directory(v) => v.is_empty(),
83            PreviewData::File(v) => v.is_empty(),
84            PreviewData::Empty => true,
85        }
86    }
87
88    pub fn iter(&self) -> impl Iterator<Item = &FileEntry> {
89        match self {
90            PreviewData::Directory(entries) => entries.iter(),
91            _ => [].iter(),
92        }
93    }
94
95    pub fn len(&self) -> usize {
96        match self {
97            PreviewData::Directory(entries) => entries.len(),
98            _ => 0,
99        }
100    }
101}
102
103impl Default for PreviewState {
104    fn default() -> Self {
105        Self {
106            data: PreviewData::Empty,
107            selected_idx: 0,
108            current_path: None,
109            request_id: 0,
110            pending: false,
111            last_input_time: Instant::now(),
112        }
113    }
114}