Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/DioxusLabs/dioxus into la…
Browse files Browse the repository at this point in the history
…zy_tui
  • Loading branch information
ealmloff committed Apr 24, 2022
2 parents 7b35566 + 6087954 commit 84db875
Show file tree
Hide file tree
Showing 22 changed files with 746 additions and 110 deletions.
64 changes: 8 additions & 56 deletions benches/tui_update.rs
Expand Up @@ -17,62 +17,14 @@ fn tui_update(c: &mut Criterion) {
&size,
|b, size| {
b.iter(|| match size {
1 => dioxus::tui::launch_cfg(
app3,
Config {
headless: true,
..Default::default()
},
),
2 => dioxus::tui::launch_cfg(
app6,
Config {
headless: true,
..Default::default()
},
),
3 => dioxus::tui::launch_cfg(
app9,
Config {
headless: true,
..Default::default()
},
),
4 => dioxus::tui::launch_cfg(
app12,
Config {
headless: true,
..Default::default()
},
),
5 => dioxus::tui::launch_cfg(
app15,
Config {
headless: true,
..Default::default()
},
),
6 => dioxus::tui::launch_cfg(
app18,
Config {
headless: true,
..Default::default()
},
),
7 => dioxus::tui::launch_cfg(
app21,
Config {
headless: true,
..Default::default()
},
),
8 => dioxus::tui::launch_cfg(
app24,
Config {
headless: true,
..Default::default()
},
),
1 => dioxus::tui::launch_cfg(app3, Config::default().with_headless()),
2 => dioxus::tui::launch_cfg(app6, Config::default().with_headless()),
3 => dioxus::tui::launch_cfg(app9, Config::default().with_headless()),
4 => dioxus::tui::launch_cfg(app12, Config::default().with_headless()),
5 => dioxus::tui::launch_cfg(app15, Config::default().with_headless()),
6 => dioxus::tui::launch_cfg(app18, Config::default().with_headless()),
7 => dioxus::tui::launch_cfg(app21, Config::default().with_headless()),
8 => dioxus::tui::launch_cfg(app24, Config::default().with_headless()),
_ => (),
})
},
Expand Down
37 changes: 37 additions & 0 deletions examples/custom_html.rs
@@ -0,0 +1,37 @@
//! This example shows how to use a custom index.html and custom <HEAD> extensions
//! to add things like stylesheets, scripts, and third-party JS libraries.

use dioxus::prelude::*;

fn main() {
dioxus::desktop::launch_cfg(app, |c| {
c.with_custom_head("<style>body { background-color: red; }</style>".into())
});

dioxus::desktop::launch_cfg(app, |c| {
c.with_custom_index(
r#"
<!DOCTYPE html>
<html>
<head>
<title>Dioxus app</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>body { background-color: blue; }</style>
</head>
<body>
<div id="main"></div>
</body>
</html>
"#
.into(),
)
});
}

fn app(cx: Scope) -> Element {
cx.render(rsx! {
div {
h1 {"hello world!"}
}
})
}
5 changes: 3 additions & 2 deletions examples/tailwind.rs
Expand Up @@ -11,12 +11,13 @@
use dioxus::prelude::*;

fn main() {
dioxus::desktop::launch(app);
dioxus::desktop::launch_cfg(app, |c| {
c.with_custom_head("<script src=\"https://cdn.tailwindcss.com\"></script>".to_string())
});
}

pub fn app(cx: Scope) -> Element {
cx.render(rsx!(
link { href:"https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css", rel:"stylesheet" }
div {
header { class: "text-gray-400 bg-gray-900 body-font",
div { class: "container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center",
Expand Down
5 changes: 1 addition & 4 deletions examples/tui_color_test.rs
Expand Up @@ -3,10 +3,7 @@ use dioxus::prelude::*;
fn main() {
dioxus::tui::launch_cfg(
app,
dioxus::tui::Config {
rendering_mode: dioxus::tui::RenderingMode::Ansi,
..Default::default()
},
dioxus::tui::Config::default().with_rendering_mode(dioxus::tui::RenderingMode::Ansi),
);
}

Expand Down
24 changes: 24 additions & 0 deletions packages/desktop/src/cfg.rs
Expand Up @@ -21,6 +21,8 @@ pub struct DesktopConfig {
pub(crate) event_handler: Option<Box<DynEventHandlerFn>>,
pub(crate) disable_context_menu: bool,
pub(crate) resource_dir: Option<PathBuf>,
pub(crate) custom_head: Option<String>,
pub(crate) custom_index: Option<String>,
}

pub(crate) type WryProtocol = (
Expand All @@ -42,6 +44,8 @@ impl DesktopConfig {
pre_rendered: None,
disable_context_menu: !cfg!(debug_assertions),
resource_dir: None,
custom_head: None,
custom_index: None,
}
}

Expand Down Expand Up @@ -100,10 +104,30 @@ impl DesktopConfig {
self
}

/// Add a custom icon for this application
pub fn with_icon(&mut self, icon: Icon) -> &mut Self {
self.window.window.window_icon = Some(icon);
self
}

/// Inject additional content into the document's HEAD.
///
/// This is useful for loading CSS libraries, JS libraries, etc.
pub fn with_custom_head(&mut self, head: String) -> &mut Self {
self.custom_head = Some(head);
self
}

/// Use a custom index.html instead of the default Dioxus one.
///
/// Make sure your index.html is valid HTML.
///
/// Dioxus injects some loader code into the closing body tag. Your document
/// must include a body element!
pub fn with_custom_index(&mut self, index: String) -> &mut Self {
self.custom_index = Some(index);
self
}
}

impl DesktopConfig {
Expand Down
2 changes: 1 addition & 1 deletion packages/desktop/src/desktop_context.rs
Expand Up @@ -201,7 +201,7 @@ pub(super) fn handler(

/// Get a closure that executes any JavaScript in the WebView context.
pub fn use_eval<S: std::string::ToString>(cx: &ScopeState) -> &dyn Fn(S) {
let desktop = use_window(&cx).clone();
let desktop = use_window(cx).clone();

cx.use_hook(|_| move |script| desktop.eval(script))
}
7 changes: 2 additions & 5 deletions packages/desktop/src/index.html
Expand Up @@ -3,13 +3,10 @@
<head>
<title>Dioxus app</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- CUSTOM HEAD -->
</head>
<body>
<div id="main"></div>
<script>
import("./index.js").then(function (module) {
module.main();
});
</script>
<!-- MODULE LOADER -->
</body>
</html>
12 changes: 8 additions & 4 deletions packages/desktop/src/lib.rs
Expand Up @@ -125,8 +125,9 @@ pub fn launch_with_props<P: 'static + Send>(
let proxy = proxy.clone();

let file_handler = cfg.file_drop_handler.take();

let custom_head = cfg.custom_head.clone();
let resource_dir = cfg.resource_dir.clone();
let index_file = cfg.custom_index.clone();

let mut webview = WebViewBuilder::new(window)
.unwrap()
Expand Down Expand Up @@ -164,7 +165,12 @@ pub fn launch_with_props<P: 'static + Send>(
});
})
.with_custom_protocol(String::from("dioxus"), move |r| {
protocol::desktop_handler(r, resource_dir.clone())
protocol::desktop_handler(
r,
resource_dir.clone(),
custom_head.clone(),
index_file.clone(),
)
})
.with_file_drop_handler(move |window, evet| {
file_handler
Expand All @@ -183,12 +189,10 @@ pub fn launch_with_props<P: 'static + Send>(
r#"
if (document.addEventListener) {
document.addEventListener('contextmenu', function(e) {
alert("You've tried to open context menu");
e.preventDefault();
}, false);
} else {
document.attachEvent('oncontextmenu', function() {
alert("You've tried to open context menu");
window.event.returnValue = false;
});
}
Expand Down
37 changes: 33 additions & 4 deletions packages/desktop/src/protocol.rs
Expand Up @@ -4,7 +4,20 @@ use wry::{
Result,
};

pub(super) fn desktop_handler(request: &Request, asset_root: Option<PathBuf>) -> Result<Response> {
const MODULE_LOADER: &str = r#"
<script>
import("./index.js").then(function (module) {
module.main();
});
</script>
"#;

pub(super) fn desktop_handler(
request: &Request,
asset_root: Option<PathBuf>,
custom_head: Option<String>,
custom_index: Option<String>,
) -> Result<Response> {
// Any content that uses the `dioxus://` scheme will be shuttled through this handler as a "special case".
// For now, we only serve two pieces of content which get included as bytes into the final binary.
let path = request.uri().replace("dioxus://", "");
Expand All @@ -13,9 +26,25 @@ pub(super) fn desktop_handler(request: &Request, asset_root: Option<PathBuf>) ->
let trimmed = path.trim_start_matches("index.html/");

if trimmed.is_empty() {
ResponseBuilder::new()
.mimetype("text/html")
.body(include_bytes!("./index.html").to_vec())
// If a custom index is provided, just defer to that, expecting the user to know what they're doing.
// we'll look for the closing </body> tag and insert our little module loader there.
if let Some(custom_index) = custom_index {
let rendered = custom_index
.replace("</body>", &format!("{}</body>", MODULE_LOADER))
.into_bytes();
ResponseBuilder::new().mimetype("text/html").body(rendered)
} else {
// Otherwise, we'll serve the default index.html and apply a custom head if that's specified.
let mut template = include_str!("./index.html").to_string();
if let Some(custom_head) = custom_head {
template = template.replace("<!-- CUSTOM HEAD -->", &custom_head);
}
template = template.replace("<!-- MODULE LOADER -->", MODULE_LOADER);

ResponseBuilder::new()
.mimetype("text/html")
.body(template.into_bytes())
}
} else if trimmed == "index.js" {
ResponseBuilder::new()
.mimetype("text/javascript")
Expand Down

0 comments on commit 84db875

Please sign in to comment.