Skip to content

Commit e7c7a3d

Browse files
committed
wip: native home-screen
1 parent bb1d7a2 commit e7c7a3d

File tree

7 files changed

+415
-10
lines changed

7 files changed

+415
-10
lines changed

application/apps/indexer/.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
**/*.rs.bk
33
**/proptest-regressions
44
*.out
5-
lineMetadata.json
65
vim-markdown-preview.html
76
.DS_Store
87
Cargo.lock
8+
*.json

application/apps/indexer/gui/application/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ anyhow.workspace = true
2929
thiserror.workspace = true
3030
clap.workspace = true
3131
serde.workspace = true
32+
serde_json.workspace = true
3233
log.workspace = true
3334
tokio.workspace = true
3435
rfd.workspace = true
Lines changed: 275 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,282 @@
1-
use egui::Ui;
1+
use crate::common::phosphor::icons;
2+
use crate::host::ui::UiActions;
3+
use crate::host::ui::home::settings::HomeSettings;
4+
use egui::{Align, Button, CentralPanel, Layout, RichText, SidePanel, Ui};
5+
6+
use std::env;
7+
8+
pub mod settings;
29

310
#[derive(Debug)]
4-
pub struct HomeView {}
11+
pub struct HomeScreen {
12+
pub state: HomeSettings,
13+
pub ui_state: UiState,
14+
pub data_path: std::path::PathBuf,
15+
}
16+
17+
#[derive(Debug, Default)]
18+
pub struct UiState {
19+
pub search: String,
20+
}
21+
22+
impl HomeScreen {
23+
pub fn new() -> Self {
24+
HomeScreen {
25+
state: HomeSettings::default(),
26+
ui_state: UiState::default(),
27+
data_path: env::current_dir().expect("current_dir"), // TODO
28+
}
29+
}
530

6-
impl HomeView {
7-
pub fn render_content(ui: &mut Ui) {
31+
pub fn render_content(&mut self, actions: &mut UiActions, ui: &mut Ui) {
832
ui.centered_and_justified(|ui| {
9-
ui.heading("Welcome to Chipmunk");
33+
//ui.heading("Welcome to Chipmunk");
34+
home_screen(ui, &mut self.state, &mut self.ui_state);
1035
});
1136
}
1237
}
38+
39+
pub fn home_screen(ui: &mut egui::Ui, state: &mut HomeSettings, search: &mut UiState) {
40+
SidePanel::left("quick actions")
41+
.width_range(50.0..=150.0)
42+
.default_width(100.)
43+
.resizable(true)
44+
.show_inside(ui, |ui| {
45+
ui.with_layout(Layout::top_down_justified(Align::LEFT), |ui| {
46+
draw_quick_actions(ui, state);
47+
});
48+
});
49+
50+
SidePanel::right("favorite folders")
51+
.width_range(150.0..=450.0)
52+
.default_width(200.)
53+
.resizable(true)
54+
.show_inside(ui, |ui| {
55+
ui.with_layout(Layout::top_down_justified(Align::LEFT), |ui| {
56+
ui.add_space(5.0);
57+
ui.heading("Favorite folders");
58+
draw_favorite_folders(ui, state, search);
59+
});
60+
});
61+
62+
CentralPanel::default().show_inside(ui, |ui| {
63+
ui.with_layout(Layout::top_down_justified(Align::LEFT), |ui| {
64+
ui.heading("Recently opened");
65+
draw_recent_files(ui, state);
66+
});
67+
});
68+
}
69+
70+
pub fn draw_quick_actions(ui: &mut egui::Ui, state: &mut HomeSettings) {
71+
let item_size = egui::vec2(ui.available_width(), 60.0);
72+
73+
egui::ScrollArea::vertical()
74+
.id_salt("quick_actions_scroll")
75+
.show(ui, |ui| {
76+
for action in &state.quick_actions {
77+
ui.push_id(&action.id, |ui| {
78+
let (rect, response) = ui.allocate_exact_size(item_size, egui::Sense::click());
79+
80+
let visuals = ui.style().interact(&response);
81+
if response.hovered() || response.is_pointer_button_down_on() {
82+
ui.painter()
83+
.rect_filled(rect.shrink(2.0), 6.0, visuals.bg_fill);
84+
}
85+
86+
let inner_rect = rect.shrink(6.0);
87+
88+
ui.scope_builder(egui::UiBuilder::new().max_rect(inner_rect), |ui| {
89+
ui.with_layout(
90+
egui::Layout::top_down_justified(egui::Align::Center),
91+
|ui| {
92+
ui.add_space(2.0);
93+
ui.label(egui::RichText::new(&action.icon).size(22.0));
94+
ui.add(
95+
egui::Label::new(egui::RichText::new(&action.label).small())
96+
.wrap_mode(egui::TextWrapMode::Truncate),
97+
);
98+
},
99+
);
100+
});
101+
102+
if response.clicked() {
103+
println!("Quick action clicked: {}", action.id);
104+
}
105+
response.on_hover_text(&action.label);
106+
107+
ui.add_space(4.0);
108+
});
109+
}
110+
});
111+
}
112+
113+
fn draw_recent_files(ui: &mut egui::Ui, state: &mut HomeSettings) {
114+
egui::ScrollArea::vertical()
115+
.id_salt("recent_files_scroll")
116+
.show(ui, |ui| {
117+
ui.label("List of recently opened sources.");
118+
ui.add_space(5.0);
119+
120+
for file in &mut state.recent_files {
121+
ui.collapsing(file.path.display().to_string(), |ui| {
122+
ui.horizontal(|ui| {
123+
if ui
124+
.add(
125+
Button::new(RichText::new(icons::regular::TRASH).size(12.0))
126+
.small(),
127+
)
128+
.on_hover_text("Remove entry")
129+
.clicked()
130+
{
131+
print!("remove recent entry...");
132+
}
133+
134+
if ui
135+
.add(
136+
Button::new(RichText::new(icons::regular::PLUS).size(12.0)).small(),
137+
)
138+
.on_hover_text("New configuration")
139+
.clicked()
140+
{
141+
print!("open new configuration...");
142+
}
143+
});
144+
145+
for cfg in &file.configurations {
146+
ui.horizontal(|ui| {
147+
if ui
148+
.add(
149+
Button::new(
150+
RichText::new(icons::regular::ARROW_SQUARE_OUT).size(12.0),
151+
)
152+
.small(),
153+
)
154+
.on_hover_text("Open configuration")
155+
.clicked()
156+
{
157+
print!("open configuration...");
158+
}
159+
160+
if ui
161+
.add(
162+
Button::new(
163+
RichText::new(icons::regular::FILE_MINUS).size(12.0),
164+
)
165+
.small(),
166+
)
167+
.on_hover_text("Remove configuration")
168+
.clicked()
169+
{
170+
print!("remove configuration...");
171+
}
172+
173+
ui.label(&cfg.name);
174+
ui.label(&cfg.info());
175+
});
176+
}
177+
});
178+
}
179+
});
180+
}
181+
182+
fn draw_favorite_folders(ui: &mut egui::Ui, state: &mut HomeSettings, ui_state: &mut UiState) {
183+
ui.horizontal(|ui| {
184+
ui.with_layout(egui::Layout::left_to_right(egui::Align::Center), |ui| {
185+
ui.label("Search:");
186+
187+
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
188+
if ui
189+
.add(Button::new(RichText::new(icons::regular::PLUS).size(12.0)).small())
190+
.on_hover_text("Add folder")
191+
.clicked()
192+
{
193+
print!("add favorites folder...");
194+
}
195+
196+
if ui
197+
.add(
198+
Button::new(RichText::new(icons::regular::ARROWS_CLOCKWISE).size(12.0))
199+
.small(),
200+
)
201+
.on_hover_text("Refresh")
202+
.clicked()
203+
{
204+
print!("refresh favorites folder...");
205+
}
206+
207+
ui.add(
208+
egui::TextEdit::singleline(&mut ui_state.search)
209+
.desired_width(f32::INFINITY)
210+
.hint_text("type to filter..."),
211+
);
212+
});
213+
});
214+
});
215+
216+
ui.add_space(2.0);
217+
218+
egui::ScrollArea::vertical()
219+
.id_salt("favorite_folders_scroll")
220+
.show(ui, |ui| {
221+
for folder in &state.favorite_folders {
222+
ui.collapsing(folder.path.display().to_string(), |ui| {
223+
if ui
224+
.add(Button::new(RichText::new(icons::regular::TRASH).size(12.0)).small())
225+
.on_hover_text("Remove folder")
226+
.clicked()
227+
{
228+
print!("remove favorite folder...");
229+
}
230+
231+
if let Ok(entries) = std::fs::read_dir(&folder.path) {
232+
for entry in entries.flatten() {
233+
let path = entry.path();
234+
235+
if let Some(name) = path.file_name() {
236+
if name.to_string_lossy().starts_with('.') {
237+
continue;
238+
}
239+
}
240+
241+
if let Ok(meta) = std::fs::symlink_metadata(&path) {
242+
if meta.file_type().is_symlink() {
243+
continue;
244+
}
245+
}
246+
247+
if !path.is_file() {
248+
continue;
249+
}
250+
251+
let name = path.file_name().unwrap().to_string_lossy();
252+
253+
if !ui_state.search.is_empty()
254+
&& !name
255+
.to_lowercase()
256+
.contains(&ui_state.search.to_lowercase())
257+
{
258+
continue;
259+
}
260+
261+
ui.horizontal(|ui| {
262+
if ui
263+
.add(
264+
Button::new(
265+
RichText::new(icons::regular::ARROW_SQUARE_OUT)
266+
.size(12.0),
267+
)
268+
.small(),
269+
)
270+
.on_hover_text("Open file")
271+
.clicked()
272+
{
273+
print!("open favorites file...");
274+
}
275+
ui.label(name.to_string());
276+
});
277+
}
278+
}
279+
});
280+
}
281+
});
282+
}

0 commit comments

Comments
 (0)