web-view 0.7.3

Rust bindings for webview, a tiny cross-platform library to render web-based GUIs for desktop applications
//#![windows_subsystem = "windows"]

#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate web_view;

use web_view::*;

fn main() {
    let html = format!(
        r#"<!doctype html>
        <html>
        <head>
            <meta http-equiv="X-UA-Compatible" content="IE=edge">
            <meta charset="UTF-8">
            {styles}
        </head>
        <body>
            <!--[if lt IE 11]>
            <div class="ie-upgrade-container">
                <p class="ie-upgrade-message">Please, upgrade Internet Explorer to continue using this software.</p>
                <a class="ie-upgrade-link" target="_blank" href="https://www.microsoft.com/en-us/download/internet-explorer.aspx">Upgrade</a>
            </div>
            <![endif]-->
            <div id="elm"></div>
            {scripts}
        </body>
        </html>
		"#,
        styles = inline_style(include_str!("todo-elm/styles.css")),
        scripts = inline_script(include_str!("todo-elm/elm.js"))
            + &inline_script(include_str!("todo-elm/app.js")),
    );

    let mut webview = web_view::builder()
        .title("Rust Todo App")
        .content(Content::Html(html))
        .size(320, 480)
        .resizable(false)
        .debug(true)
        .user_data(vec![])
        .invoke_handler(|webview, arg| {
            use Cmd::*;

            let tasks_len = {
                let tasks = webview.user_data_mut();

                match serde_json::from_str(arg).unwrap() {
                    Init => {
                        *tasks = vec![Task {
                            name: "Create Elm example".to_string(),
                            done: true,
                        }];
                    }
                    Log { text } => println!("{}", text),
                    AddTask { name } => tasks.push(Task { name, done: false }),
                    MarkTask { index, done } => tasks[index].done = done,
                    ClearDoneTasks => tasks.retain(|t| !t.done),
                }

                tasks.len()
            };

            webview.set_title(&format!("Rust Todo App ({} Tasks)", tasks_len))?;
            render(webview)
        })
        .build()
        .unwrap();

    webview.set_color((156, 39, 176));

    let res = webview.run().unwrap();

    println!("final state: {:?}", res);
}

fn render(webview: &mut WebView<Vec<Task>>) -> WVResult {
    let render_tasks = {
        let tasks = webview.user_data();
        println!("{:#?}", tasks);
        format!(
            "app.ports.fromRust.send({})",
            serde_json::to_string(tasks).unwrap()
        )
    };
    webview.eval(&render_tasks)
}

#[derive(Debug, Serialize, Deserialize)]
struct Task {
    name: String,
    done: bool,
}

#[derive(Deserialize)]
#[serde(tag = "cmd")]
pub enum Cmd {
    Init,
    Log { text: String },
    AddTask { name: String },
    MarkTask { index: usize, done: bool },
    ClearDoneTasks,
}

fn inline_style(s: &str) -> String {
    format!(r#"<style type="text/css">{}</style>"#, s)
}

fn inline_script(s: &str) -> String {
    format!(r#"<script type="text/javascript">{}</script>"#, s)
}