初试tauri开发图形化应用

最后编辑时间: 2023-03-27

前言

  • 在notion-rss发布后,有用户评论不太会使用命令行工具,所以想写给命令行写一个图形化界面,经过调研,最后选择了tauri。下面来记录一下使用tauri开发图形化界面的过程和坑。

Rust的GUI框架对比

  • state-of-rust-gui-libraries这篇文章对比了rust常见的gui库,主要在是否跨平台开发,是否能已经成熟能用在生产环境。
  • 经过比较感觉fltk-rs和tauri还行的,gtk的整个架构太大了,就编译工具链就劝退了,然后下面很多都是基于gtk封装了一层,让用户使用起来不再这么麻烦,还有要学习多一种标记语言,学习成本太高了。
  Production ready Compatibility
gtk-rs Yes Cross-platform
fltk-rs Yes Cross-platform
iced No Cross-platform and web
relm No Cross-platform
Azul Yes Cross-platform
egui Older Releases Cross-platform
Tauri Yes Desktop and web
Slint Yes Web
Druid Yes Desktop and web
  • 最后因为fltk-rs不够现代化,选了Tauri。主要看生态了文档,Tauri只需要用HTML写完前端,真正的所见及所得,本来也会Vue,几个UI库,所以不用再学什么东西,直接可以上手。
  • electron的对比,总之吊打electron。

环境搭建

  • 安装create-tauri-app
➜ cargo install create-tauri-app
➜ cargo install tauri-cli

初始化项目

  • 如果已经有项目了,可以创建完再拷贝进文件里,改一下文件名,rust的源文件在src-tauri,前端项目源文件在src,两个都可以分别开发。
➜  IdeaProjects cargo create-tauri-app

✔ Project name · tauri-app
✔ Choose your package manager · cargo
✔ Choose your UI template · vanilla

Please follow <https://tauri.app/v1/guides/getting-started/prerequisites> to install the needed prerequisites, if you haven't already.
You also need to install tauri-cli (cargo install tauri-cli)

Done, Now run:
  cd tauri-app
  cargo tauri dev

➜  IdeaProjects
  • 这样创建的项目前端是纯HTML,JS的,开发大项目不太适合,建议先开始写前端,再进去前端目录用cargo tauri init初始taruri项目。

tauri.conf.json

  • 初始化完成后会在src-tauri文件夹生成配置文件tauri.conf.json,可以开启和关闭一些危险模块,设置分发参数。

自定义icon图标

  • 执行下面命令可以生成各个格式大小的图标。
➜  notion-rss git:(main) ✗ cargo tauri icon src-tauri/icons/index.ico

Window系统隐藏命令行控制台

  • 加入编译参数修改子系统为window
#![cfg_attr(
    all(not(debug_assertions), target_os = "windows"),
    windows_subsystem = "windows"
)]

Rust与前端互相调用

前端调用Rust

  • 文档,这里只放一个例子,Rust里被调用的代码,
#[tauri::command]
pub async fn init_user() -> Option<notion_sdk::user::User> {
    if let Ok(Object::User { user }) = NOTION_FEED.notion.users_me().await {
        return Some(user);
    }
    None
}
  • invoke_handler注册调用方法generate_handler
let builder = tauri::Builder::default()
            .system_tray(tauri::SystemTray::new().with_menu(MyTray::tray_menu()))
            .setup(|app| {
                resolve_setup(app);
                Ok(())
            })
            .on_system_tray_event(MyTray::on_system_tray_event)
            .invoke_handler(tauri::generate_handler![
                notion_rss::ui::save_config,
                notion_rss::ui::init_config,
                notion_rss::ui::init_user,
                notion_rss::ui::update_once,
                notion_rss::ui::run_api_server
            ]);
  • 在前端就可以使用invoke调用init_user
// 初始化用户信息
    async init_user() {
      if (
        this.config.notion_token &&
        this.config.archive_id &&
        this.config.source_id
      ) {
        invoke("init_user")
          .then((response) => {
            this.user = response;
          })
          .catch((error) => {
            this.snackbar = { text: error, show: true, color: "error" };
          });
      }
    },

Rust调用前端

  • 文档,在Rust调用前端需要用到事件,首先要在前端页面创建一个监听事件,下面只是把从Rust发送过来的Paylad通过snackbar提示出来,防止多次监听这段代码要在created方法中调用。PROGRESS为你监听的事件。
// 监听事件
    async event_listen() {
      await appWindow.listen("PROGRESS", ({ event, payload }) => {
        console.log(event, payload);
        this.snackbar = {
          text: payload.toString(),
          show: true,
          color: "success",
        };
        this.update_loading = false;
      });
    },
  • 在Rust中接收一个tauri::Window类型的参数
#[tauri::command]
pub async fn update_once(window: tauri::Window) {
    update(Some(window.clone())).await;
}
  • 要推送信息时调用window的emit方法就可以将Payload推送到PROGRESS监听事件中。
window.emit("PROGRESS", err.to_string()).unwrap_or_default();

发布版本

  • 官方在github中有action,发布版本只需要创建CI文件改改就可以了,非常方便,缺点是没办法静态编译,没办法自定义文件名。所以Mac系统的M1架构暂时没发布。

参考

请在下方留下您的评论.加入TG吹水群