gikoha’s blog

個人的メモがわり

Rustでweb-view GUI (2)

  • web-view の login form test

    • html から 文字を入力し rust に渡すだけのプログラム

    • html 側のデータは javascript側から JSONで rustに送る

    • rust からは webview.evalで javascript側に データを送る

    • ただ bindingするだけなら swiftや Kotlinのほうが楽ちん

  • IntelliJの tabnineが強力すぎる...

cargo.toml

[package]
name = "testlogin"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
web-view = { version = "0.7" }
serde = { version = "1.0", features = ["derive"] }
serde_json="1.0"
regex="1"

lib.js

var Login = {};

Login.doLogin = function doLogin(loginForm) {
    if(loginForm.username.value == '') {
        return Login.doError('ユーザー名を入力してください。');
    }
    if(loginForm.password.value == '') {
        return Login.doError('パスワードを入力してください。');
    }
    var ans_data = { login: loginForm.username.value, password: loginForm.password.value };
    external.invoke( JSON.stringify(ans_data));
    return false;
}

Login.doError = function doError(msg) {
    document.getElementById('display').innerHTML = msg;
    return false;
}

main.rs

use regex::Regex;
use serde::{Deserialize, Serialize};
use web_view::*;

//参考:https://zenn.dev/yukit/articles/02a02ef025feff

//jsonを色々考えないでいい文字列に変換する
pub fn json_to_encodestr(s: &str) -> String {
    let _quote = Regex::new("\"").unwrap();
    _quote.replace_all(s, "&q;").to_string()
}

//色々考えないでいい文字列からjsonに戻す
pub fn encodestr_to_json(s: &str) -> String {
    let _quote = Regex::new("&q;").unwrap();
    _quote.replace_all(s, "\"").to_string()
}

#[derive(Serialize, Deserialize, Debug)]
struct LoginForm {
    login: String,
    password: String,
}

fn main() {
    let html_content = std::format!(
        r#"<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
        <script>
        {}
        </script>
</head>
    <body>
        <form id="loginform" action="" method="post" onsubmit="return Login.doLogin(this)">
      <label>login:
      <input type="text" name="username" value="" /></label>
      <br />
      <label>password:
      <input type="password" name="password" value="" /></label>
      <br />

        <input type="submit" value="login" />
        </form>
        <br />
        <div id="display">not logged in</div>

    </body>
</html>"#,
        include_str!("lib.js")
    );

    // 動作確認; macOS 11.5(64bit arm/intel), Windows 10(64bit) Windows 7 (32bit), 起動不可; Windows 2000
    let webview = web_view::builder()
        .title("Login Demo")
        .content(Content::Html(html_content))
        .size(320, 240)
        .user_data(())
        .invoke_handler(|_webview, arg| {
            let decode_arg = encodestr_to_json(arg);
            if let Ok(res) = serde_json::from_str(&decode_arg) as Result<LoginForm, _> {
                println!(
                    "===> invoke_handler : login:{} pass:{}",
                    res.login, res.password
                );
            }
            Ok(())
        })
        .build()
        .unwrap();

    webview.run().unwrap();
}