#![allow(unused)] use std::{ cell::Cell, time::{Duration, Instant}, }; use sledgehammer_bindgen::bindgen; use wry::http::Response; #[cfg(any(target_os = "android", target_os = "windows"))] const INDEX_PATH: &str = "http://dioxus.index.html"; #[cfg(not(any(target_os = "android", target_os = "windows")))] const INDEX_PATH: &str = "dioxus://index.html"; const TYPED_JS: &str = include_str!("./typed_elements.js"); #[bindgen] mod js { #[extends(TypedElements)] struct Channel; fn create_element(id: u16, element_id: u8) { "this.nodes[$id$]=document.createElement(this.els[$element_id$]);" } fn set_attribute(id: u16, attribute_id: u8, val: impl Writable) { "this.nodes[$id$].setAttribute(this.attrs[$attribute_id$],$val$);" } fn remove_attribute(id: u16, attribute_id: u8) { "this.nodes[$id$].removeAttribute(this.attrs[$attribute_id$]);" } fn append_child(id: u16, id2: u16) { "this.nodes[$id$].appendChild(this.nodes[$id2$]);" } fn insert_before(parent: u16, id: u16, id2: u16) { "this.nodes[$parent$].insertBefore(this.nodes[$id$],this.nodes[$id2$]);" } fn set_text(id: u16, text: impl Writable) { "this.nodes[$id$].textContent=$text$;" } fn remove(id: u16) { "this.nodes[$id$].remove();" } fn replace(id: u16, id2: u16) { "this.nodes[$id$].replaceWith(this.nodes[$id2$]);" } fn clone(id: u16, id2: u16) { "this.nodes[$id2$]=this.nodes[$id$].cloneNode(true);" } fn first_child(id: u16) { "this.node[id]=this.node[id].firstChild;" } fn next_sibling(id: u16) { "this.node[id]=this.node[id].nextSibling;" } } #[allow(non_camel_case_types)] #[repr(u8)] enum Element { a, abbr, acronym, address, applet, area, article, aside, audio, b, base, bdi, bdo, bgsound, big, blink, blockquote, body, br, button, canvas, caption, center, cite, code, col, colgroup, content, data, datalist, dd, del, details, dfn, dialog, dir, div, dl, dt, em, embed, fieldset, figcaption, figure, font, footer, form, frame, frameset, h1, head, header, hgroup, hr, html, i, iframe, image, img, input, ins, kbd, keygen, label, legend, li, link, main, map, mark, marquee, menu, menuitem, meta, meter, nav, nobr, noembed, noframes, noscript, object, ol, optgroup, option, output, p, param, picture, plaintext, portal, pre, progress, q, rb, rp, rt, rtc, ruby, s, samp, script, section, select, shadow, slot, small, source, spacer, span, strike, strong, style, sub, summary, sup, table, tbody, td, template, textarea, tfoot, th, thead, time, title, tr, track, tt, u, ul, var, video, wbr, xmp, } #[allow(non_camel_case_types)] #[repr(u8)] enum Attribute { ccept_charset, accept, accesskey, action, align, allow, alt, aria_atomic, aria_busy, aria_controls, aria_current, aria_describedby, aria_description, aria_details, aria_disabled, aria_dropeffect, aria_errormessage, aria_flowto, aria_grabbed, aria_haspopup, aria_hidden, aria_invalid, aria_keyshortcuts, aria_label, aria_labelledby, aria_live, aria_owns, aria_relevant, aria_roledescription, r#async, autocapitalize, autocomplete, autofocus, autoplay, background, bgcolor, border, buffered, capture, challenge, charset, checked, cite, class, code, codebase, color, cols, colspan, content, contenteditable, contextmenu, controls, coords, crossorigin, csp, data, datetime, decoding, default, defer, dir, dirname, disabled, download, draggable, enctype, enterkeyhint, r#for, form, formaction, formenctype, formmethod, formnovalidate, formtarget, headers, height, hidden, high, href, hreflang, http_equiv, icon, id, importance, inputmode, integrity, intrinsicsize, ismap, itemprop, keytype, kind, label, lang, language, list, loading, r#loop, low, manifest, max, maxlength, media, method, min, minlength, multiple, muted, name, novalidate, open, optimum, pattern, ping, placeholder, poster, preload, radiogroup, readonly, referrerpolicy, rel, required, reversed, role, rows, rowspan, sandbox, scope, scoped, selected, shape, size, sizes, slot, span, spellcheck, src, srcdoc, srclang, srcset, start, step, style, summary, tabindex, target, title, translate, r#type, usemap, value, width, wrap, } fn main() -> wry::Result<()> { use wry::{ application::{ event::{Event, StartCause, WindowEvent}, event_loop::{ControlFlow, EventLoop}, window::WindowBuilder, }, webview::WebViewBuilder, }; let event_loop = EventLoop::new(); let window = WindowBuilder::new() .with_title("Hello World") .build(&event_loop)?; let first_request = Cell::new(true); let _webview = WebViewBuilder::new(window)? .with_url(INDEX_PATH) .unwrap() .with_asynchronous_custom_protocol("dioxus".into(), move |_, responder| { if first_request.get() { first_request.set(false); let html = format!( r#"
"#, TYPED_JS, GENERATED_JS.replace("export", "") ); responder.respond( Response::builder() .header("Access-Control-Allow-Origin", "*") .header("Content-Type", "text/html") .body(html.as_bytes().to_vec()) .unwrap(), ); return; } let mut channel1 = Channel::default(); let main = 0; let node1 = 1; let node2 = 2; for _ in 0..rand::random::() { channel1.create_element(node1, Element::div as u8); channel1.create_element(node2, Element::span as u8); channel1.append_child(node1, node2); let rand1 = rand::random::(); let rand2 = rand::random::(); channel1.set_text( node2, format_args!("{}+{}={}", rand1, rand2, rand1 as usize + rand2 as usize), ); channel1.append_child(main, node1); } let data = channel1.export_memory(); let data: Vec<_> = data.collect(); println!("{:?}", data); channel1.reset(); std::thread::spawn(move || { std::thread::sleep(Duration::from_millis(100)); responder.respond(Response::new(data)); }); }) .build()?; event_loop.run(move |event, _, control_flow| { *control_flow = ControlFlow::Wait; match event { Event::NewEvents(StartCause::Init) => {} Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => *control_flow = ControlFlow::Exit, _ => (), } }); }