🐥

TauriとLeptosで作るデスクトップアプリ(3)バックエンドを呼び出す

2024/08/19に公開

はじめに

TauriとLeptosでデスクトップアプリを作っていきます。今回は、LeptosフロントエンドからTauriバックエンドのコマンドを呼び出します。あわせて、デバッグ用にフロントエンドのコンソールにログを表示できるようにします。

関連記事
環境
  • Windows 11 Home
  • Rust 1.80
  • Tauri 2.0.0-rc

https://v2.tauri.app/

  • Leptos 0.7.0-beta

https://leptos.dev/

依存パッケージを追加する

  • ロギングを行う

Tauriバックエンド側では、標準出力はそのままcargo tauri devを実行したターミナルに表示されます。Leptosフロントエンド側では、ソースコード内でprintln!()としても、どこにも表示されません。開発者ツールのコンソールでログを確認できるようにlogconsole_logを追加します。

  • Tarui APIをRustフロントエンドで扱う

Rustフロントエンド側でTauri APIにバインディングするためにtauri-sysを追加します。同時にシリアライズするためにserdeを追加します。

上記2つをあわせて、./apps/src-ui/Cargo.toml[dependencies]を以下のように更新します。

./apps/src-ui/Cargo.toml
[dependencies]
# 略
log = "0.4.22"
console_log = "1.0.0"
serde = { version = "1", features = ["derive"] }

[dependencies.tauri-sys]
git = "https://github.com/JonasKruckenberg/tauri-sys"
branch = "v2"
features = ["all"]

あいさつコンポーネントを作成する

Tauriのcreate-tauri-appでも自動で作られる「あいさつ」コンポーネントを作成します。LeptosフロントエンドからTauriバックエンドにStringを送信し、それを加工してTauriバックエンドからLeptosフロントエンドにStringを返信します。

Leptosフロントエンドクレート./apps/src-ui内のcomponentsモジュールにgreetサブモジュールを作ります。ディレクトリ構成は以下のとおりです。

tauri-leptos-example
├─ apps/
│  ├─ src-tauri/
│  └─ src-ui/
│     ├─ src/
│     │  ├─ components/
│     │  │  ├─ counter.rs
│     │  │  ├─ greet.rs
│     │  │  └─ mod.rs
│     │  ├─ app.rs
│     │  ├─ lib.rs
:     :  └─ main.rs

mod.rsgreetサブモジュールの宣言を追加します。

./apps/src-ui/src/components/mod.rs
pub mod counter;
pub mod greet;

greet.rsにあいさつコンポーネントを実装します。

./apps/src-ui/src/components/greet.rs
use leptos::prelude::*;
use serde::Serialize;
use thaw::{Button, ButtonAppearance, Input, Tag};

#[derive(Serialize)]
struct GreetArgs {
    name: String,
}

#[component]
pub fn Greet() -> impl IntoView {
    let name = RwSignal::new(String::new());
    let greet_msg = RwSignal::new(String::new());

    let on_click = move |_| {
        leptos::spawn::spawn_local(async move {
            let name = name.get_untracked();
            log::info!("invoke: {name}");
            let args = GreetArgs { name };
            let msg: String = tauri_sys::core::invoke("greet", args).await;
            greet_msg.set(msg);
        })
    };

    view! {
        <div>
            <Input placeholder="Enter a name..." value=name />
            <Button appearance=ButtonAppearance::Primary on_click>
                "Greet"
            </Button>
            <Tag>{greet_msg}</Tag>
        </div>
    }
}

on_click関数の中でlog::info!("invoke: {name}");としています。これで、開発者ツールのコンソールにログが表示されます。tauri_sysを使うと、Tauriバックエンドのコマンド呼び出しがinvoke()関数で簡単にできます。view!マクロの<Button>コンポーネントでは、on_click属性が変数と同名なので、短縮表記をしています。また、ボタンのスタイルをappearance属性で指定しています。

以下、LeptosフロントエンドのRustソースコードを変更します。

./apps/src-ui/src/components/app.rs
use leptos::prelude::*;
use thaw::ConfigProvider;

use crate::components::counter::SimpleCounter;
use crate::components::greet::Greet;

#[component]
pub fn App() -> impl IntoView {
    view! {
        <ConfigProvider>
            <SimpleCounter initial_value=0 step=1 />
            <Greet />
        </ConfigProvider>
    }
}
./apps/src-ui/src/components/lib.rs
use app::App;
use leptos::prelude::*;

mod app;
pub mod components;

pub fn run() {
    console_log::init().expect("error initializing logger");
    console_error_panic_hook::set_once();
    mount_to_body(App)
}

lib.rsでは、console_log::init()でログレベルをINFOに変更しています。

バックエンドでコマンドを用意する

Tauriバックエンドクレート./apps/src-tauri内でRustソースコードを実装します。ディレクトリ構成は以下のとおりです。

tauri-leptos-example
├─ apps/
│  ├─ src-tauri/
│  │  ├─ src/
│  │  │  ├─ commands.rs
│  │  │  ├─ lib.rs
│  │  :  └─ main.rs
:  └─ src-ui/

commands.rsにコマンドを書きます。今回はStringを受け取って、Stringを返す単純な関数です。引数の名前nameは、Leptosフロントエンドで用意した構造体GreetArgsのフィード名に一致する必要があります。

./apps/src-tauri/src/commands.rs
#[tauri::command]
pub fn greet(name: String) -> String {
    println!("invoked: {name}");
    format!("Hello, {name}!")
}

lib.rsでコマンドを実装した関数をハンドラに登録します。

./apps/src-tauri/src/lib.rs
mod commands;

pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_shell::init())
        .invoke_handler(tauri::generate_handler![commands::greet])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

プロジェクトを実行します。

> cargo tauri dev

greet

期待どおりの動作が確認できました。

コマンド呼び出しのテスト行う

TODO

サンプルコード

今回作成したプロジェクトは以下からダウンロード可能です。

https://github.com/daizutabi/tauri-leptos-example/tree/0.3

GitHubで編集を提案

Discussion