CLI Fixes & Tweaks (#2846)
Fixes scrolling on vscode using simple fix Adds scroll modifier, scroll at 5 lines per scroll while holding shift key. Adds error handling for manganis failure that still lets the build run. Revises TUI rendering code. Move TUI "info bars" to the bottom of the terminal. Revised logging system with tracing Working [c] clear keybind. This has been removed. Removal of [h] hide keybind text (it does nothing) Some opinionated cleanups and renames to make tui logic easier to understand. Rolling log file & maybe add some more "internal" logging. Closes CLI Rolling Log File #2764 Removes log tabs. Closes CLI: Color-code logs and get rid of tabs #2857 Combines info bars. Working and good text selection. Print launch URL in console. Handle log lines properly and add formatting. Move MessageSource to a more reasonable location. Add some background styling to powerline (info bar) - Tried this and it doesn't look the greatest. Log Filtering Final Cleaning & Changes - I could do this forever Test Linux --------- Co-authored-by: Jonathan Kelley <jkelleyrtp@gmail.com>
This commit is contained in:
1 parent
87c2f64f13
commit
8d68886310
22 files changed
+1302
-718
No files matched your search
@@ -1,11 +1,14 @@
|
||||
use std::future::{poll_fn, Future, IntoFuture};
|
||||
use std::task::Poll;
|
||||
|
||||
use crate::builder::{Stage, TargetPlatform, UpdateBuildProgress, UpdateStage};
|
||||
use crate::cli::serve::Serve;
|
||||
use crate::dioxus_crate::DioxusCrate;
|
||||
use crate::tracer::CLILogControl;
|
||||
use crate::Result;
|
||||
use crate::{
|
||||
builder::{Stage, TargetPlatform, UpdateBuildProgress, UpdateStage},
|
||||
TraceSrc,
|
||||
};
|
||||
use futures_util::FutureExt;
|
||||
use tokio::task::yield_now;
|
||||
|
||||
@@ -54,6 +57,8 @@ pub async fn serve_all(
|
||||
dioxus_crate: DioxusCrate,
|
||||
log_control: CLILogControl,
|
||||
) -> Result<()> {
|
||||
// Start the screen first so we collect build logs.
|
||||
let mut screen = Output::start(&serve, log_control).expect("Failed to open terminal logger");
|
||||
let mut builder = Builder::new(&dioxus_crate, &serve);
|
||||
|
||||
// Start the first build
|
||||
@@ -61,7 +66,6 @@ pub async fn serve_all(
|
||||
|
||||
let mut server = Server::start(&serve, &dioxus_crate);
|
||||
let mut watcher = Watcher::start(&serve, &dioxus_crate);
|
||||
let mut screen = Output::start(&serve, log_control).expect("Failed to open terminal logger");
|
||||
|
||||
let is_hot_reload = serve.server_arguments.hot_reload.unwrap_or(true);
|
||||
|
||||
@@ -81,15 +85,21 @@ pub async fn serve_all(
|
||||
}
|
||||
|
||||
let changed_files = watcher.dequeue_changed_files(&dioxus_crate);
|
||||
let changed = changed_files.first().cloned();
|
||||
|
||||
// if change is hotreloadable, hotreload it
|
||||
// and then send that update to all connected clients
|
||||
if let Some(hr) = watcher.attempt_hot_reload(&dioxus_crate, changed_files) {
|
||||
// Only send a hotreload message for templates and assets - otherwise we'll just get a full rebuild
|
||||
if hr.templates.is_empty() && hr.assets.is_empty() {
|
||||
if hr.templates.is_empty() && hr.assets.is_empty() && hr.unknown_files.is_empty() {
|
||||
continue
|
||||
}
|
||||
|
||||
if let Some(changed_path) = changed {
|
||||
let path_relative = changed_path.strip_prefix(dioxus_crate.crate_dir()).map(|p| p.display().to_string()).unwrap_or_else(|_| changed_path.display().to_string());
|
||||
tracing::info!(dx_src = ?TraceSrc::Dev, "Hotreloaded {}", path_relative);
|
||||
}
|
||||
|
||||
server.send_hotreload(hr).await;
|
||||
} else {
|
||||
// If the change is not binary patchable, rebuild the project
|
||||
@@ -129,7 +139,7 @@ pub async fn serve_all(
|
||||
match application {
|
||||
Ok(BuilderUpdate::Progress { platform, update }) => {
|
||||
let update_clone = update.clone();
|
||||
screen.new_build_logs(platform, update_clone);
|
||||
screen.new_build_progress(platform, update_clone);
|
||||
server.update_build_status(screen.build_progress.progress(), update.stage.to_string()).await;
|
||||
|
||||
match update {
|
||||
@@ -151,7 +161,7 @@ pub async fn serve_all(
|
||||
match child {
|
||||
Ok(Some(child_proc)) => builder.children.push((build_result.target_platform, child_proc)),
|
||||
Err(e) => {
|
||||
tracing::error!("Failed to open build result: {e}");
|
||||
tracing::error!(dx_src = ?TraceSrc::Build, "Failed to open build result: {e}");
|
||||
break;
|
||||
},
|
||||
_ => {}
|
||||
@@ -176,11 +186,11 @@ pub async fn serve_all(
|
||||
break;
|
||||
}
|
||||
else {
|
||||
tracing::error!("Application exited with status: {status}");
|
||||
tracing::error!(dx_src = ?TraceSrc::Dev, "Application exited with status: {status}");
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
tracing::error!("Application exited with error: {e}");
|
||||
tracing::error!(dx_src = ?TraceSrc::Dev, "Application exited with error: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+301
-471
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,487 @@
|
||||
use super::{BuildProgress, TraceMsg, TraceSrc};
|
||||
use ansi_to_tui::IntoText as _;
|
||||
use dioxus_cli_config::Platform;
|
||||
use ratatui::{
|
||||
layout::{Alignment, Constraint, Direction, Layout, Rect},
|
||||
style::{Color, Style, Stylize},
|
||||
text::{Line, Span, Text},
|
||||
widgets::{Block, Borders, Clear, List, ListState, Paragraph, Widget, Wrap},
|
||||
Frame,
|
||||
};
|
||||
use regex::Regex;
|
||||
use std::fmt::Write as _;
|
||||
use std::rc::Rc;
|
||||
use tracing::Level;
|
||||
|
||||
pub struct TuiLayout {
|
||||
/// The entire TUI body.
|
||||
_body: Rc<[Rect]>,
|
||||
/// The console where build logs are displayed.
|
||||
console: Rc<[Rect]>,
|
||||
// The filter drawer if the drawer is open.
|
||||
filter_drawer: Option<Rc<[Rect]>>,
|
||||
|
||||
// The border that separates the console and info bars.
|
||||
border_sep: Rect,
|
||||
|
||||
// The status bar that displays build status, platform, versions, etc.
|
||||
status_bar: Rc<[Rect]>,
|
||||
|
||||
// Misc
|
||||
filter_list_state: ListState,
|
||||
}
|
||||
|
||||
impl TuiLayout {
|
||||
pub fn new(frame_size: Rect, filter_open: bool) -> Self {
|
||||
// The full layout
|
||||
let body = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([
|
||||
// Footer Status
|
||||
Constraint::Length(1),
|
||||
// Border Separator
|
||||
Constraint::Length(1),
|
||||
// Console
|
||||
Constraint::Fill(1),
|
||||
// Padding
|
||||
Constraint::Length(1),
|
||||
])
|
||||
.split(frame_size);
|
||||
|
||||
let mut console_constraints = vec![Constraint::Fill(1)];
|
||||
if filter_open {
|
||||
console_constraints.push(Constraint::Length(1));
|
||||
console_constraints.push(Constraint::Length(25));
|
||||
}
|
||||
|
||||
// Build the console, where logs go.
|
||||
let console = Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints(console_constraints)
|
||||
.split(body[2]);
|
||||
|
||||
let filter_drawer = match filter_open {
|
||||
false => None,
|
||||
true => Some(
|
||||
Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints([
|
||||
Constraint::Length(1),
|
||||
Constraint::Fill(1),
|
||||
Constraint::Length(1),
|
||||
])
|
||||
.split(console[2]),
|
||||
),
|
||||
};
|
||||
|
||||
// Build the status bar.
|
||||
let status_bar = Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints([Constraint::Fill(1), Constraint::Fill(1)])
|
||||
.split(body[0]);
|
||||
|
||||
// Specify borders
|
||||
let border_sep_top = body[1];
|
||||
|
||||
Self {
|
||||
_body: body,
|
||||
console,
|
||||
filter_drawer,
|
||||
border_sep: border_sep_top,
|
||||
status_bar,
|
||||
filter_list_state: ListState::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Render all decorations.
|
||||
pub fn render_decor(&self, frame: &mut Frame, filter_open: bool) {
|
||||
frame.render_widget(
|
||||
Block::new()
|
||||
.borders(Borders::TOP)
|
||||
.border_style(Style::new().white()),
|
||||
self.border_sep,
|
||||
);
|
||||
|
||||
if filter_open {
|
||||
frame.render_widget(
|
||||
Block::new()
|
||||
.borders(Borders::LEFT)
|
||||
.border_style(Style::new().white()),
|
||||
self.console[1],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Render the console and it's logs, returning the number of lines required to render the entire log output.
|
||||
pub fn render_console(
|
||||
&self,
|
||||
frame: &mut Frame,
|
||||
scroll_position: u16,
|
||||
messages: &[TraceMsg],
|
||||
enabled_filters: &[String],
|
||||
) -> u16 {
|
||||
const LEVEL_MAX: usize = "BUILD: ".len();
|
||||
|
||||
let mut out_text = Text::default();
|
||||
|
||||
// Assemble the messages
|
||||
for msg in messages.iter() {
|
||||
let mut sub_line_padding = 0;
|
||||
|
||||
let text = msg.content.trim_end().into_text().unwrap_or_default();
|
||||
|
||||
for (idx, line) in text.lines.into_iter().enumerate() {
|
||||
// Don't add any formatting for cargo messages.
|
||||
let out_line = if msg.source != TraceSrc::Cargo {
|
||||
if idx == 0 {
|
||||
match msg.source {
|
||||
TraceSrc::Dev => {
|
||||
let mut spans = vec![Span::from(" DEV: ").light_magenta()];
|
||||
|
||||
for span in line.spans {
|
||||
spans.push(span);
|
||||
}
|
||||
spans
|
||||
}
|
||||
TraceSrc::Build => {
|
||||
let mut spans = vec![Span::from("BUILD: ").light_blue()];
|
||||
|
||||
for span in line.spans {
|
||||
spans.push(span);
|
||||
}
|
||||
spans
|
||||
}
|
||||
_ => {
|
||||
// Build level tag: `INFO:``
|
||||
// We don't subtract 1 here for `:` because we still want at least 1 padding.
|
||||
let padding =
|
||||
build_msg_padding(LEVEL_MAX - msg.level.to_string().len() - 2);
|
||||
let level = format!("{padding}{}: ", msg.level);
|
||||
sub_line_padding += level.len();
|
||||
|
||||
let level_span = Span::from(level);
|
||||
let level_span = match msg.level {
|
||||
Level::TRACE => level_span.black(),
|
||||
Level::DEBUG => level_span.light_magenta(),
|
||||
Level::INFO => level_span.light_green(),
|
||||
Level::WARN => level_span.light_yellow(),
|
||||
Level::ERROR => level_span.light_red(),
|
||||
};
|
||||
|
||||
let mut out_line = vec![level_span];
|
||||
for span in line.spans {
|
||||
out_line.push(span);
|
||||
}
|
||||
|
||||
out_line
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Not the first line. Append the padding and merge into list.
|
||||
let padding = build_msg_padding(sub_line_padding);
|
||||
|
||||
let mut out_line = vec![Span::from(padding)];
|
||||
for span in line.spans {
|
||||
out_line.push(span);
|
||||
}
|
||||
out_line
|
||||
}
|
||||
} else {
|
||||
line.spans
|
||||
};
|
||||
|
||||
out_text.push_line(Line::from(out_line));
|
||||
}
|
||||
}
|
||||
|
||||
// Only show messages for filters that are enabled.
|
||||
let mut included_line_ids = Vec::new();
|
||||
|
||||
for filter in enabled_filters {
|
||||
let re = Regex::new(filter);
|
||||
for (index, line) in out_text.lines.iter().enumerate() {
|
||||
let line_str = line.to_string();
|
||||
match re {
|
||||
Ok(ref re) => {
|
||||
// sort by provided regex
|
||||
if re.is_match(&line_str) {
|
||||
included_line_ids.push(index);
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
// default to basic string storing
|
||||
if line_str.contains(filter) {
|
||||
included_line_ids.push(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
included_line_ids.sort_unstable();
|
||||
included_line_ids.dedup();
|
||||
|
||||
let out_lines = out_text.lines;
|
||||
let mut out_text = Text::default();
|
||||
|
||||
if enabled_filters.is_empty() {
|
||||
for line in out_lines {
|
||||
out_text.push_line(line.clone());
|
||||
}
|
||||
} else {
|
||||
for id in included_line_ids {
|
||||
if let Some(line) = out_lines.get(id) {
|
||||
out_text.push_line(line.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (console_width, _console_height) = self.get_console_size();
|
||||
|
||||
let paragraph = Paragraph::new(out_text)
|
||||
.left_aligned()
|
||||
.wrap(Wrap { trim: false });
|
||||
|
||||
let num_lines_wrapping = paragraph.line_count(console_width) as u16;
|
||||
|
||||
paragraph
|
||||
.scroll((scroll_position, 0))
|
||||
.render(self.console[0], frame.buffer_mut());
|
||||
|
||||
num_lines_wrapping
|
||||
}
|
||||
|
||||
/// Render the status bar.
|
||||
pub fn render_status_bar(
|
||||
&self,
|
||||
frame: &mut Frame,
|
||||
_platform: Platform,
|
||||
build_progress: &BuildProgress,
|
||||
more_modal_open: bool,
|
||||
filter_menu_open: bool,
|
||||
dx_version: &str,
|
||||
) {
|
||||
// left aligned text
|
||||
let mut spans = vec![
|
||||
Span::from("🧬 dx").white(),
|
||||
Span::from(" ").white(),
|
||||
Span::from(dx_version).white(),
|
||||
Span::from(" | ").dark_gray(),
|
||||
];
|
||||
|
||||
// If there is build progress, render the current status.
|
||||
let is_build_progress = !build_progress.current_builds.is_empty();
|
||||
if is_build_progress {
|
||||
// If the build failed, show a failed status.
|
||||
// Otherwise, render current status.
|
||||
let build_failed = build_progress
|
||||
.current_builds
|
||||
.values()
|
||||
.any(|b| b.failed.is_some());
|
||||
|
||||
if build_failed {
|
||||
spans.push(Span::from("Build failed ❌").red());
|
||||
} else {
|
||||
// spans.push(Span::from("status: ").gray());
|
||||
let build = build_progress
|
||||
.current_builds
|
||||
.values()
|
||||
.min_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal))
|
||||
.unwrap();
|
||||
spans.extend_from_slice(&build.make_spans(Rect::new(
|
||||
0,
|
||||
0,
|
||||
build.max_layout_size(),
|
||||
1,
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
// right aligned text
|
||||
let more_span = Span::from("[/] more");
|
||||
let more_span = match more_modal_open {
|
||||
true => more_span.light_yellow(),
|
||||
false => more_span.gray(),
|
||||
};
|
||||
|
||||
let filter_span = Span::from("[f] filter");
|
||||
let filter_span = match filter_menu_open {
|
||||
true => filter_span.light_yellow(),
|
||||
false => filter_span.gray(),
|
||||
};
|
||||
|
||||
// Right-aligned text
|
||||
let right_line = Line::from(vec![
|
||||
Span::from("[o] open").gray(),
|
||||
Span::from(" | ").gray(),
|
||||
Span::from("[r] rebuild").gray(),
|
||||
Span::from(" | ").gray(),
|
||||
filter_span,
|
||||
Span::from(" | ").dark_gray(),
|
||||
more_span,
|
||||
]);
|
||||
|
||||
frame.render_widget(
|
||||
Paragraph::new(Line::from(spans)).left_aligned(),
|
||||
self.status_bar[0],
|
||||
);
|
||||
|
||||
// Render the info
|
||||
frame.render_widget(
|
||||
Paragraph::new(right_line).right_aligned(),
|
||||
self.status_bar[1],
|
||||
);
|
||||
}
|
||||
|
||||
/// Renders the "more" modal to show extra info/keybinds accessible via the more keybind.
|
||||
pub fn render_more_modal(&self, frame: &mut Frame) {
|
||||
let modal = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([Constraint::Fill(1), Constraint::Length(5)])
|
||||
.split(self.console[0])[1];
|
||||
|
||||
frame.render_widget(Clear, modal);
|
||||
frame.render_widget(Block::default().borders(Borders::ALL), modal);
|
||||
|
||||
// Render under construction message
|
||||
frame.render_widget(
|
||||
Paragraph::new("Under construction, please check back at a later date!")
|
||||
.alignment(Alignment::Center),
|
||||
modal,
|
||||
);
|
||||
}
|
||||
|
||||
/// Render the filter drawer menu.
|
||||
pub fn render_filter_menu(
|
||||
&mut self,
|
||||
frame: &mut Frame,
|
||||
filters: &[(String, bool)],
|
||||
selected_filter_index: usize,
|
||||
search_mode: bool,
|
||||
search_input: Option<&String>,
|
||||
) {
|
||||
let Some(ref filter_drawer) = self.filter_drawer else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Vertical layout
|
||||
let container = Layout::default()
|
||||
.constraints([
|
||||
Constraint::Length(4),
|
||||
Constraint::Fill(1),
|
||||
Constraint::Length(7),
|
||||
])
|
||||
.direction(Direction::Vertical)
|
||||
.split(filter_drawer[1]);
|
||||
|
||||
// Render the search section.
|
||||
let top_area = Layout::default()
|
||||
.constraints([
|
||||
Constraint::Length(1),
|
||||
Constraint::Length(1),
|
||||
Constraint::Length(1),
|
||||
Constraint::Length(1),
|
||||
])
|
||||
.direction(Direction::Vertical)
|
||||
.split(container[0]);
|
||||
|
||||
let search_title = Line::from("Search").gray();
|
||||
let search_input_block = Block::new().bg(Color::White);
|
||||
|
||||
let search_text = match search_input {
|
||||
Some(s) => s,
|
||||
None => {
|
||||
if search_mode {
|
||||
"..."
|
||||
} else {
|
||||
"[enter] to type..."
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let search_input = Paragraph::new(Line::from(search_text))
|
||||
.fg(Color::Black)
|
||||
.block(search_input_block);
|
||||
|
||||
frame.render_widget(search_title, top_area[1]);
|
||||
frame.render_widget(search_input, top_area[2]);
|
||||
|
||||
// Render the filters
|
||||
let list_area = container[1];
|
||||
let mut list_items = Vec::new();
|
||||
|
||||
for (filter, enabled) in filters {
|
||||
let filter = Span::from(filter);
|
||||
let filter = match enabled {
|
||||
true => filter.light_yellow(),
|
||||
false => filter.dark_gray(),
|
||||
};
|
||||
list_items.push(filter);
|
||||
}
|
||||
list_items.reverse();
|
||||
|
||||
let list = List::new(list_items).highlight_symbol("» ");
|
||||
self.filter_list_state.select(Some(selected_filter_index));
|
||||
frame.render_stateful_widget(list, list_area, &mut self.filter_list_state);
|
||||
|
||||
// Render the keybind list at the bottom.
|
||||
let keybinds = container[2];
|
||||
let lines = vec![
|
||||
Line::from(""),
|
||||
Line::from("[↑] Up").white(),
|
||||
Line::from("[↓] Down").white(),
|
||||
Line::from("[←] Remove").white(),
|
||||
Line::from("[→] Toggle").white(),
|
||||
Line::from("[enter] Type / Submit").white(),
|
||||
];
|
||||
let text = Text::from(lines);
|
||||
frame.render_widget(text, keybinds);
|
||||
}
|
||||
|
||||
/// Returns the height of the console TUI area in number of lines.
|
||||
pub fn get_console_size(&self) -> (u16, u16) {
|
||||
(self.console[0].width, self.console[0].height)
|
||||
}
|
||||
|
||||
/// Render the current scroll position at the top right corner of the frame
|
||||
pub(crate) fn render_current_scroll(
|
||||
&self,
|
||||
scroll_position: u16,
|
||||
lines: u16,
|
||||
console_height: u16,
|
||||
frame: &mut Frame<'_>,
|
||||
) {
|
||||
let mut row = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([Constraint::Length(1)])
|
||||
.split(self.console[0])[0];
|
||||
|
||||
// Hack: shove upwards the text to overlap with the border so text selection doesn't accidentally capture the number
|
||||
row.y -= 1;
|
||||
|
||||
let max_scroll = lines.saturating_sub(console_height);
|
||||
if max_scroll == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let remaining_lines = max_scroll.saturating_sub(scroll_position);
|
||||
if remaining_lines != 0 {
|
||||
let text = vec![Span::from(format!(" {remaining_lines}⬇ ")).dark_gray()];
|
||||
frame.render_widget(
|
||||
Paragraph::new(Line::from(text))
|
||||
.alignment(Alignment::Right)
|
||||
.block(Block::default()),
|
||||
row,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a string with a specified number of spaces.
|
||||
fn build_msg_padding(padding_len: usize) -> String {
|
||||
let mut padding = String::new();
|
||||
for _ in 0..padding_len {
|
||||
_ = write!(padding, " ");
|
||||
}
|
||||
padding
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::TraceSrc;
|
||||
use crate::{Error, Result};
|
||||
use dioxus_cli_config::WebProxyConfig;
|
||||
|
||||
@@ -123,7 +124,7 @@ pub(crate) fn proxy_to(
|
||||
}
|
||||
|
||||
fn handle_proxy_error(e: Error) -> axum::http::Response<axum::body::Body> {
|
||||
tracing::error!("Proxy error: {}", e);
|
||||
tracing::error!(dx_src = ?TraceSrc::Dev, "Proxy error: {}", e);
|
||||
axum::http::Response::builder()
|
||||
.status(axum::http::StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(axum::body::Body::from(format!(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::dioxus_crate::DioxusCrate;
|
||||
use crate::serve::{next_or_pending, Serve};
|
||||
use crate::{dioxus_crate::DioxusCrate, TraceSrc};
|
||||
use crate::{Error, Result};
|
||||
use axum::extract::{Request, State};
|
||||
use axum::middleware::{self, Next};
|
||||
@@ -7,7 +7,7 @@ use axum::{
|
||||
body::Body,
|
||||
extract::{
|
||||
ws::{Message, WebSocket},
|
||||
Extension, WebSocketUpgrade,
|
||||
WebSocketUpgrade,
|
||||
},
|
||||
http::{
|
||||
header::{HeaderName, HeaderValue, CACHE_CONTROL, EXPIRES, PRAGMA},
|
||||
@@ -15,7 +15,7 @@ use axum::{
|
||||
},
|
||||
response::IntoResponse,
|
||||
routing::{get, get_service},
|
||||
Router,
|
||||
Extension, Router,
|
||||
};
|
||||
use axum_server::tls_rustls::RustlsConfig;
|
||||
use dioxus_cli_config::{Platform, WebHttpsConfig};
|
||||
@@ -569,8 +569,12 @@ pub fn get_rustls_with_mkcert(web_config: &WebHttpsConfig) -> Result<(String, St
|
||||
match cmd {
|
||||
Err(e) => {
|
||||
match e.kind() {
|
||||
io::ErrorKind::NotFound => tracing::error!("mkcert is not installed. See https://github.com/FiloSottile/mkcert#installation for installation instructions."),
|
||||
e => tracing::error!("an error occurred while generating mkcert certificates: {}", e.to_string()),
|
||||
io::ErrorKind::NotFound => {
|
||||
tracing::error!(dx_src = ?TraceSrc::Dev, "`mkcert` is not installed. See https://github.com/FiloSottile/mkcert#installation for installation instructions.")
|
||||
}
|
||||
e => {
|
||||
tracing::error!(dx_src = ?TraceSrc::Dev, "An error occurred while generating mkcert certificates: {}", e.to_string())
|
||||
}
|
||||
};
|
||||
return Err("failed to generate mkcert certificates".into());
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::{fs, path::PathBuf, time::Duration};
|
||||
|
||||
use super::hot_reloading_file_map::HotreloadError;
|
||||
use crate::serve::hot_reloading_file_map::FileMap;
|
||||
use crate::TraceSrc;
|
||||
use crate::{cli::serve::Serve, dioxus_crate::DioxusCrate};
|
||||
use dioxus_hot_reload::HotReloadMsg;
|
||||
use dioxus_html::HtmlCtx;
|
||||
@@ -258,7 +259,7 @@ impl Watcher {
|
||||
Err(HotreloadError::Parse) => {}
|
||||
// Otherwise just log the error
|
||||
Err(err) => {
|
||||
tracing::error!("Error hotreloading file {rust_file:?}: {err}")
|
||||
tracing::error!(dx_src = ?TraceSrc::Dev, "Error hotreloading file {rust_file:?}: {err}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user