Skip to content

Commit 497dd3e

Browse files
authored
Project Does Not Exists Notification (#191)
* project does not exists notification the project lists * fix cargo fmt errors
1 parent 34982fe commit 497dd3e

File tree

2 files changed

+101
-3
lines changed

2 files changed

+101
-3
lines changed

crates/bevy_editor_launcher/src/main.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,10 @@ fn main() {
9494
.add_systems(Startup, ui::setup)
9595
.add_systems(
9696
Update,
97-
poll_create_project_task.run_if(run_if_task_is_running),
97+
(
98+
poll_create_project_task.run_if(run_if_task_is_running),
99+
ui::handle_notification_popups,
100+
),
98101
)
99102
.configure_sets(Startup, FooterBarSet.after(ui::setup))
100103
.run();

crates/bevy_editor_launcher/src/ui.rs

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::io::ErrorKind;
2+
use std::path::Path;
23

34
use bevy::{prelude::*, ui::RelativeCursorPosition};
45
use bevy_editor::project::{run_project, set_project_list, templates::Templates, ProjectInfo};
@@ -13,6 +14,66 @@ use crate::ProjectInfoList;
1314
#[require(Node)]
1415
pub struct ProjectList;
1516

17+
/// Component for notification popup
18+
#[derive(Component)]
19+
pub struct NotificationPopup {
20+
pub timer: Timer,
21+
}
22+
23+
/// System to handle notification popups
24+
pub fn handle_notification_popups(
25+
mut commands: Commands,
26+
time: Res<Time>,
27+
mut query: Query<(Entity, &mut NotificationPopup)>,
28+
) {
29+
for (entity, mut popup) in query.iter_mut() {
30+
popup.timer.tick(time.delta());
31+
if popup.timer.finished() {
32+
commands.entity(entity).despawn();
33+
}
34+
}
35+
}
36+
37+
/// Spawn a notification popup with a message
38+
pub fn spawn_notification_popup(commands: &mut Commands, theme: &Theme, message: &str) -> Entity {
39+
commands
40+
.spawn((
41+
Node {
42+
position_type: PositionType::Absolute,
43+
left: Val::Px(0.0),
44+
right: Val::Px(0.0),
45+
top: Val::Px(50.0),
46+
margin: UiRect::horizontal(Val::Auto),
47+
padding: UiRect::all(Val::Px(12.0)),
48+
width: Val::Auto,
49+
height: Val::Auto,
50+
align_items: AlignItems::Center,
51+
justify_content: JustifyContent::Center,
52+
..default()
53+
},
54+
BackgroundColor(Color::srgba(0.1, 0.1, 0.1, 0.9)),
55+
BorderRadius::all(Val::Px(8.0)),
56+
NotificationPopup {
57+
timer: Timer::from_seconds(3.0, TimerMode::Once),
58+
},
59+
))
60+
.with_child((
61+
Text::new(message.to_string()),
62+
TextFont {
63+
font: theme.text.font.clone(),
64+
font_size: 18.0,
65+
..default()
66+
},
67+
TextColor(Color::WHITE),
68+
Outline {
69+
width: Val::Px(0.5),
70+
color: Color::BLACK,
71+
..default()
72+
},
73+
))
74+
.id()
75+
}
76+
1677
pub fn setup(
1778
mut commands: Commands,
1879
theme: Res<Theme>,
@@ -140,7 +201,8 @@ pub(crate) fn spawn_project_node<'a>(
140201
query_children: Query<&Children>,
141202
query_text: Query<&Text>,
142203
mut exit: EventWriter<AppExit>,
143-
mut project_list: ResMut<ProjectInfoList>| {
204+
mut project_list: ResMut<ProjectInfoList>,
205+
theme: Res<Theme>| {
144206
let project = {
145207
let text = {
146208
let project_entity = trigger.target();
@@ -165,6 +227,25 @@ pub(crate) fn spawn_project_node<'a>(
165227
.clone()
166228
};
167229

230+
// Check if project directory exists before trying to run it
231+
if !Path::new(&project.path).exists() {
232+
// Show notification popup
233+
let project_name = project.name().unwrap_or_else(|| "Unknown".to_string());
234+
spawn_notification_popup(
235+
&mut commands,
236+
&theme,
237+
&format!("Project not found: '{project_name}'"),
238+
);
239+
// Remove project from list
240+
project_list.0.retain(|p| p.path != project.path);
241+
set_project_list(project_list.0.clone());
242+
// Remove project node from UI
243+
let project_entity = trigger.target();
244+
commands.entity(project_entity).despawn();
245+
return;
246+
}
247+
248+
// Project exists, try to run it
168249
match run_project(&project) {
169250
Ok(_) => {
170251
exit.send(AppExit::Success);
@@ -173,14 +254,28 @@ pub(crate) fn spawn_project_node<'a>(
173254
error!("Failed to run project: {:?}", error);
174255
match error.kind() {
175256
ErrorKind::NotFound | ErrorKind::InvalidData => {
257+
// Show notification popup
258+
let project_name = project.name().unwrap_or_else(|| "Unknown".to_string());
259+
spawn_notification_popup(
260+
&mut commands,
261+
&theme,
262+
&format!("Failed to run project: '{project_name}'"),
263+
);
176264
// Remove project from list
177265
project_list.0.retain(|p| p.path != project.path);
178266
set_project_list(project_list.0.clone());
179267
// Remove project node from UI
180268
let project_entity = trigger.target();
181269
commands.entity(project_entity).despawn();
182270
}
183-
_ => {}
271+
_ => {
272+
// Show generic error notification
273+
spawn_notification_popup(
274+
&mut commands,
275+
&theme,
276+
&format!("Error running project: '{error}'"),
277+
);
278+
}
184279
}
185280
}
186281
}

0 commit comments

Comments
 (0)