diff --git a/extra/man/rio.1.scd b/extra/man/rio.1.scd index 33bd537b..d9cd9613 100644 --- a/extra/man/rio.1.scd +++ b/extra/man/rio.1.scd @@ -89,4 +89,4 @@ Found a bug? Please report it at _https://github.com/raphamorim/rio/issues_. # MAINTAINERS -- Raphael Amorim +- Raphael Amorim diff --git a/frontends/rioterm/src/application.rs b/frontends/rioterm/src/application.rs index 05d5a761..83e32112 100644 --- a/frontends/rioterm/src/application.rs +++ b/frontends/rioterm/src/application.rs @@ -965,6 +965,11 @@ impl ApplicationHandler for Application<'_> { } } + if route.window.screen.handle_assistant_click() { + route.request_redraw(); + return; + } + if route.window.screen.handle_palette_click() { route.request_redraw(); return; @@ -1091,6 +1096,38 @@ impl ApplicationHandler for Application<'_> { route.window.screen.mouse.x = x; route.window.screen.mouse.y = y; + // Handle assistant overlay hover + if route.window.screen.renderer.assistant.is_active() { + let scale = route.window.screen.sugarloaf.scale_factor(); + let win_w = route.window.screen.sugarloaf.window_size().width as f32; + let mx = x as f32 / scale; + let my = y as f32 / scale; + if route + .window + .screen + .renderer + .assistant + .hover(mx, my, win_w, scale) + { + route.window.screen.render(); + route.request_redraw(); + } + + if route + .window + .screen + .renderer + .assistant + .hovered_button() + .is_some() + { + route.window.winit_window.set_cursor(CursorIcon::Pointer); + } else { + route.window.winit_window.set_cursor(CursorIcon::Default); + } + return; + } + // Handle command palette hover if route.window.screen.renderer.command_palette.is_enabled() { let scale = route.window.screen.sugarloaf.scale_factor(); @@ -1363,7 +1400,7 @@ impl ApplicationHandler for Application<'_> { } WindowEvent::Ime(ime) => { - if route.path == RoutePath::Assistant { + if route.window.screen.renderer.assistant.is_active() { return; } @@ -1452,7 +1489,7 @@ impl ApplicationHandler for Application<'_> { } WindowEvent::DroppedFile(path) => { - if route.path == RoutePath::Assistant { + if route.window.screen.renderer.assistant.is_active() { return; } @@ -1487,13 +1524,10 @@ impl ApplicationHandler for Application<'_> { route.begin_render(); match route.path { - RoutePath::Assistant => { - route.window.screen.render_assistant(&route.assistant); - } RoutePath::Welcome => { route.window.screen.render_welcome(); } - RoutePath::Terminal => { + RoutePath::Assistant | RoutePath::Terminal => { if let Some(window_update) = route.window.screen.render() { use crate::context::renderable::{ BackgroundState, WindowUpdate, diff --git a/frontends/rioterm/src/renderer/mod.rs b/frontends/rioterm/src/renderer/mod.rs index 32fa6ecc..cb1665b8 100644 --- a/frontends/rioterm/src/renderer/mod.rs +++ b/frontends/rioterm/src/renderer/mod.rs @@ -1,3 +1,4 @@ +pub mod assistant; mod char_cache; pub mod command_palette; mod font_cache; @@ -52,6 +53,7 @@ pub struct Renderer { pub config_blinking_interval: u64, ignore_selection_fg_color: bool, pub search: search::SearchOverlay, + pub assistant: assistant::AssistantOverlay, #[allow(unused)] pub option_as_alt: String, #[allow(unused)] @@ -130,6 +132,7 @@ impl Renderer { named_colors, dynamic_background, search: search::SearchOverlay::default(), + assistant: assistant::AssistantOverlay::default(), font_cache: FontCache::new(), font_context: font_context.clone(), char_cache: CharCache::new(), @@ -1120,6 +1123,11 @@ impl Renderer { ); } + self.assistant.render( + sugarloaf, + (window_size.width, window_size.height, scale_factor), + ); + self.search.render( sugarloaf, (window_size.width, window_size.height, scale_factor), diff --git a/frontends/rioterm/src/router/mod.rs b/frontends/rioterm/src/router/mod.rs index c979ef59..0e45ef2d 100644 --- a/frontends/rioterm/src/router/mod.rs +++ b/frontends/rioterm/src/router/mod.rs @@ -127,12 +127,17 @@ impl Route<'_> { } self.assistant.set(error.to_owned()); - self.path = RoutePath::Assistant; + self.window + .screen + .renderer + .assistant + .set_error(error.to_owned()); } #[inline] pub fn clear_errors(&mut self) { self.assistant.clear(); + self.window.screen.renderer.assistant.clear(); self.path = RoutePath::Terminal; } @@ -261,13 +266,15 @@ impl Route<'_> { } let is_enter = key_event.logical_key == Key::Named(NamedKey::Enter); - if self.path == RoutePath::Assistant { - if self.assistant.is_warning() && is_enter { + + // Handle assistant overlay dismiss + if self.window.screen.renderer.assistant.is_active() { + if self.window.screen.renderer.assistant.is_warning() && is_enter { self.assistant.clear(); - self.path = RoutePath::Terminal; - } else { - return true; + self.window.screen.renderer.assistant.clear(); + self.window.screen.render(); } + return true; } if self.path == RoutePath::ConfirmQuit { diff --git a/frontends/rioterm/src/screen/mod.rs b/frontends/rioterm/src/screen/mod.rs index a6c373b1..f9e10e4c 100644 --- a/frontends/rioterm/src/screen/mod.rs +++ b/frontends/rioterm/src/screen/mod.rs @@ -2246,6 +2246,67 @@ impl Screen<'_> { } } + #[inline] + pub fn handle_assistant_click(&mut self) -> bool { + if !self.renderer.assistant.is_active() { + return false; + } + + let scale_factor = self.sugarloaf.scale_factor(); + let window_width = self.sugarloaf.window_size().width as f32; + let mouse_x = self.mouse.x as f32 / scale_factor; + let mouse_y = self.mouse.y as f32 / scale_factor; + + match self.renderer.assistant.hit_test( + mouse_x, + mouse_y, + window_width, + scale_factor, + ) { + Ok(Some(action)) => { + use crate::renderer::assistant::AssistantOverlayAction; + match action { + AssistantOverlayAction::Close => { + self.renderer.assistant.clear(); + } + AssistantOverlayAction::OpenDocs => { + Self::open_docs_url(); + } + } + self.render(); + true + } + Ok(None) => { + // Clicked inside overlay but not on a button + true + } + Err(()) => { + // Clicked outside — close the assistant overlay + self.renderer.assistant.clear(); + self.render(); + true + } + } + } + + fn open_docs_url() { + let url = "https://rioterm.com/docs/config"; + #[cfg(target_os = "macos")] + { + let _ = std::process::Command::new("open").arg(url).spawn(); + } + #[cfg(not(any(target_os = "macos", windows)))] + { + let _ = std::process::Command::new("xdg-open").arg(url).spawn(); + } + #[cfg(windows)] + { + let _ = std::process::Command::new("cmd") + .args(["/c", "start", "", url]) + .spawn(); + } + } + pub fn handle_island_click(&mut self, window: &rio_window::window::Window) -> bool { // Only handle if navigation is enabled if !self.renderer.navigation.is_enabled() { diff --git a/misc/osx/Rio.app/Contents/Info.plist b/misc/osx/Rio.app/Contents/Info.plist index f59df9eb..089663cc 100644 --- a/misc/osx/Rio.app/Contents/Info.plist +++ b/misc/osx/Rio.app/Contents/Info.plist @@ -83,7 +83,7 @@ CFBundleIdentifier com.raphaelamorim.rio CFBundleGetInfoString - Hardware-accelerated GPU terminal emulator. More information: https://raphamorim.io/rio/ + Hardware-accelerated GPU terminal emulator. More information: https://rioterm.com/ CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/rio-backend/src/config/defaults.rs b/rio-backend/src/config/defaults.rs index 7eb4a8d3..fbb5b8c9 100644 --- a/rio-backend/src/config/defaults.rs +++ b/rio-backend/src/config/defaults.rs @@ -507,8 +507,6 @@ pub fn default_config_file_content() -> String { # Bindings # # Create custom Key bindings for Rio terminal -# More information in: https://raphamorim.io/rio/docs/key-bindings -# # Example: # [bindings] # keys = [ diff --git a/rio-backend/src/error/mod.rs b/rio-backend/src/error/mod.rs index a85da485..24bde4fc 100644 --- a/rio-backend/src/error/mod.rs +++ b/rio-backend/src/error/mod.rs @@ -93,7 +93,7 @@ impl std::fmt::Display for RioErrorType { } RioErrorType::IgnoredReport => write!(f, ""), RioErrorType::InvalidConfigurationFormat(message) => { - write!(f, "Found an issue loading the configuration file:\n\n{message}\n\nRio will proceed with the default configuration\nhttps://raphamorim.io/rio/docs/config") + write!(f, "Found an issue loading the configuration file:\n\n{message}\n\nRio will proceed with the default configuration") } RioErrorType::InvalidConfigurationTheme(message) => { write!(f, "Found an issue in the configured theme:\n\n{message}")