[omg] GUI, mDNS, list games on client start
7
crates/lanspread-tauri-leptos/src-tauri/.gitignore
vendored
Executable file
@ -0,0 +1,7 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
|
||||
# Generated by Tauri
|
||||
# will have schema files for capabilities auto-completion
|
||||
/gen/schemas
|
34
crates/lanspread-tauri-leptos/src-tauri/Cargo.toml
Executable file
@ -0,0 +1,34 @@
|
||||
[package]
|
||||
name = "lanspread-tauri-leptos"
|
||||
version = "0.1.0"
|
||||
description = "A Tauri App"
|
||||
authors = ["you"]
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
# The `_lib` suffix may seem redundant but it is necessary
|
||||
# to make the lib name unique and wouldn't conflict with the bin name.
|
||||
# This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519
|
||||
name = "lanspread_tauri_leptos_lib"
|
||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2", features = [] }
|
||||
|
||||
[dependencies]
|
||||
# local
|
||||
lanspread-client = { path = "../../lanspread-client" }
|
||||
lanspread-db = { path = "../../lanspread-db" }
|
||||
lanspread-mdns = { path = "../../lanspread-mdns" }
|
||||
|
||||
# external
|
||||
eyre = { workspace = true }
|
||||
log = "0.4"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
tauri = { version = "2", features = [] }
|
||||
tauri-plugin-log = "2"
|
||||
tauri-plugin-shell = "2"
|
||||
tokio = { version = "1.41", features = ["full"] }
|
3
crates/lanspread-tauri-leptos/src-tauri/build.rs
Executable file
@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
tauri_build::build()
|
||||
}
|
10
crates/lanspread-tauri-leptos/src-tauri/capabilities/default.json
Executable file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "default",
|
||||
"description": "Capability for the main window",
|
||||
"windows": ["main"],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"shell:allow-open"
|
||||
]
|
||||
}
|
BIN
crates/lanspread-tauri-leptos/src-tauri/icons/128x128.png
Executable file
After Width: | Height: | Size: 3.4 KiB |
BIN
crates/lanspread-tauri-leptos/src-tauri/icons/128x128@2x.png
Executable file
After Width: | Height: | Size: 6.8 KiB |
BIN
crates/lanspread-tauri-leptos/src-tauri/icons/32x32.png
Executable file
After Width: | Height: | Size: 974 B |
BIN
crates/lanspread-tauri-leptos/src-tauri/icons/Square107x107Logo.png
Executable file
After Width: | Height: | Size: 2.8 KiB |
BIN
crates/lanspread-tauri-leptos/src-tauri/icons/Square142x142Logo.png
Executable file
After Width: | Height: | Size: 3.8 KiB |
BIN
crates/lanspread-tauri-leptos/src-tauri/icons/Square150x150Logo.png
Executable file
After Width: | Height: | Size: 3.9 KiB |
BIN
crates/lanspread-tauri-leptos/src-tauri/icons/Square284x284Logo.png
Executable file
After Width: | Height: | Size: 7.6 KiB |
BIN
crates/lanspread-tauri-leptos/src-tauri/icons/Square30x30Logo.png
Executable file
After Width: | Height: | Size: 903 B |
BIN
crates/lanspread-tauri-leptos/src-tauri/icons/Square310x310Logo.png
Executable file
After Width: | Height: | Size: 8.4 KiB |
BIN
crates/lanspread-tauri-leptos/src-tauri/icons/Square44x44Logo.png
Executable file
After Width: | Height: | Size: 1.3 KiB |
BIN
crates/lanspread-tauri-leptos/src-tauri/icons/Square71x71Logo.png
Executable file
After Width: | Height: | Size: 2.0 KiB |
BIN
crates/lanspread-tauri-leptos/src-tauri/icons/Square89x89Logo.png
Executable file
After Width: | Height: | Size: 2.4 KiB |
BIN
crates/lanspread-tauri-leptos/src-tauri/icons/StoreLogo.png
Executable file
After Width: | Height: | Size: 1.5 KiB |
BIN
crates/lanspread-tauri-leptos/src-tauri/icons/icon.icns
Executable file
BIN
crates/lanspread-tauri-leptos/src-tauri/icons/icon.ico
Executable file
After Width: | Height: | Size: 85 KiB |
BIN
crates/lanspread-tauri-leptos/src-tauri/icons/icon.png
Executable file
After Width: | Height: | Size: 14 KiB |
127
crates/lanspread-tauri-leptos/src-tauri/src/lib.rs
Executable file
@ -0,0 +1,127 @@
|
||||
use std::{net::SocketAddr, process::Command};
|
||||
|
||||
use lanspread_client::{ClientCommand, ClientEvent};
|
||||
use lanspread_mdns::{discover_service, LANSPREAD_INSTANCE_NAME, LANSPREAD_SERVICE_TYPE};
|
||||
use tauri::{AppHandle, Emitter as _, Manager};
|
||||
use tokio::sync::{mpsc::UnboundedSender, Mutex};
|
||||
|
||||
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
||||
|
||||
struct LanSpreadState {
|
||||
server_addr: Mutex<Option<SocketAddr>>,
|
||||
client_ctrl: UnboundedSender<ClientCommand>,
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn request_games(state: tauri::State<LanSpreadState>) {
|
||||
log::debug!("request_games");
|
||||
|
||||
if let Err(e) = state.inner().client_ctrl.send(ClientCommand::ListGames) {
|
||||
log::error!("Failed to send message to client: {e:?}");
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn run_game_backend(id: u64, state: tauri::State<LanSpreadState>) -> String {
|
||||
log::error!("Running game with id {id}");
|
||||
|
||||
let result = Command::new(r#"C:\Users\ddidderr\scoop\apps\mpv\0.39.0\mpv.exe"#).spawn();
|
||||
|
||||
if let Err(e) = state.inner().client_ctrl.send(ClientCommand::GetGame(id)) {
|
||||
log::error!("Failed to send message to client: {e:?}");
|
||||
}
|
||||
|
||||
if result.is_ok() {
|
||||
"Ok".to_string()
|
||||
} else {
|
||||
"Failed to run game".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
async fn find_server(app: AppHandle) {
|
||||
log::error!("Looking for server...");
|
||||
|
||||
loop {
|
||||
match discover_service(LANSPREAD_SERVICE_TYPE, Some(LANSPREAD_INSTANCE_NAME)) {
|
||||
Ok(server_addr) => {
|
||||
log::info!("Found server at {server_addr}");
|
||||
let state: tauri::State<LanSpreadState> = app.state();
|
||||
{
|
||||
// mutex scope
|
||||
let mut addr = state.server_addr.lock().await;
|
||||
*addr = Some(server_addr);
|
||||
}
|
||||
state
|
||||
.client_ctrl
|
||||
.send(ClientCommand::ServerAddr(server_addr))
|
||||
.unwrap();
|
||||
request_games(state);
|
||||
break;
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("Failed to find server: {e} - retrying...");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
let tauri_logger_builder = tauri_plugin_log::Builder::new()
|
||||
.clear_targets()
|
||||
.target(tauri_plugin_log::Target::new(
|
||||
tauri_plugin_log::TargetKind::Stdout,
|
||||
))
|
||||
.level(log::LevelFilter::Info)
|
||||
.level_for("lanspread_client", log::LevelFilter::Debug)
|
||||
.level_for("lanspread_tauri_leptos_lib", log::LevelFilter::Debug)
|
||||
.level_for("mdns_sd::service_daemon", log::LevelFilter::Off);
|
||||
|
||||
// channel to pass commands to the client
|
||||
let (tx_client_control, rx_client_control) =
|
||||
tokio::sync::mpsc::unbounded_channel::<ClientCommand>();
|
||||
|
||||
// channel to receive events from the client
|
||||
let (tx_client_event, mut rx_client_event) =
|
||||
tokio::sync::mpsc::unbounded_channel::<ClientEvent>();
|
||||
|
||||
let lanspread_state = LanSpreadState {
|
||||
server_addr: Mutex::new(None),
|
||||
client_ctrl: tx_client_control,
|
||||
};
|
||||
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_logger_builder.build())
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.invoke_handler(tauri::generate_handler![run_game_backend, request_games])
|
||||
.manage(lanspread_state)
|
||||
.setup(|app| {
|
||||
let app_handle = app.handle().clone();
|
||||
// discover server
|
||||
tauri::async_runtime::spawn(async move { find_server(app_handle).await });
|
||||
tauri::async_runtime::spawn(async move {
|
||||
lanspread_client::run(rx_client_control, tx_client_event).await
|
||||
});
|
||||
|
||||
let app_handle = app.handle().clone();
|
||||
tauri::async_runtime::spawn(async move {
|
||||
while let Some(event) = rx_client_event.recv().await {
|
||||
log::debug!("Received client event: {event:?}");
|
||||
|
||||
match event {
|
||||
ClientEvent::ListGames(games) => {
|
||||
if let Err(e) = app_handle.emit("games-list-updated", Some(games)) {
|
||||
log::error!("Failed to emit games-list-updated event: {e}");
|
||||
} else {
|
||||
log::info!("Emitted games-list-updated event");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
6
crates/lanspread-tauri-leptos/src-tauri/src/main.rs
Executable file
@ -0,0 +1,6 @@
|
||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
fn main() {
|
||||
lanspread_tauri_leptos_lib::run()
|
||||
}
|
36
crates/lanspread-tauri-leptos/src-tauri/tauri.conf.json
Executable file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "lanspread-tauri-leptos",
|
||||
"version": "0.1.0",
|
||||
"identifier": "com.lanspread-tauri-leptos.app",
|
||||
"build": {
|
||||
"beforeDevCommand": "trunk serve",
|
||||
"devUrl": "http://localhost:1420",
|
||||
"beforeBuildCommand": "trunk build",
|
||||
"frontendDist": "../dist"
|
||||
},
|
||||
"app": {
|
||||
"withGlobalTauri": true,
|
||||
"windows": [
|
||||
{
|
||||
"title": "lanspread-tauri-leptos",
|
||||
"width": 800,
|
||||
"height": 600
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"csp": null
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": "all",
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
]
|
||||
}
|
||||
}
|