Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ dist
src-tauri/target
src-tauri/gen
.DS_Store

# tsc -b 的增量缓存
*.tsbuildinfo
2 changes: 1 addition & 1 deletion src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion src-tauri/capabilities/default.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "主窗口的能力。Tauri v2 的 capability 漏配是静默失败 —— 加一个新命令就要回来确认这里有它。",
"description": "主窗口的能力。Tauri v2 的 capability 漏配是静默失败 —— 加一个新命令就要回来确认这里有它。start-dragging 是同一个坑的实例:标题栏是 Overlay,没有一条真的标题栏可以抓,窗口全靠 data-tauri-drag-region 移动,而那条权限不在 core:window 的默认集合里。少了它拖拽区毫无反应,也不报错。",
"windows": [
"main"
],
Expand All @@ -11,6 +11,7 @@
"core:window:allow-hide",
"core:window:allow-close",
"core:window:allow-set-focus",
"core:window:allow-start-dragging",
"core:app:allow-app-hide",
"core:event:default",
"core:tray:default",
Expand Down
41 changes: 41 additions & 0 deletions src-tauri/src/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,26 @@ impl ControlClient {
.await
}

/// 生成一把新的网关密钥。**不写进配置** —— 只是拿一个值去填。
///
/// 在 core 里生成,不在界面里:字母表和长度是安全决定,两处各写
/// 一份的话迟早只有一处被改。
pub async fn new_key(&self) -> Result<String> {
let body = self.get("/keys/new").await?;
let k: tw_api::NewKey = serde_json::from_slice(&body)?;
Ok(k.key)
}

/// 这台机器上有哪些网卡。
///
/// **每次现问,不缓存。**插拔网线、连上另一个 Wi-Fi、起一条 VPN,
/// 清单就变了 —— 缓存下来只会让选单里出现一个已经不存在的地址,
/// 而选中它的后果是网关起不来。
pub async fn interfaces(&self) -> Result<Vec<tw_api::NicView>> {
let body = self.get("/interfaces").await?;
Ok(serde_json::from_slice(&body)?)
}

/// 界面要显示的配置概览。
pub async fn overview(&self) -> Result<tw_api::Overview> {
let body = self.get("/overview").await?;
Expand Down Expand Up @@ -574,6 +594,27 @@ impl ControlClient {
mod tests {
use super::*;

/// 界面发出来的每一种补丁操作,这一层都要认得。
///
/// **这条缝是真的裂过。**`tw-api` 是按 rev 锁在 core 的 main 上的,
/// 而补丁协议加一种操作时,界面这边只是多写一个字符串 —— TypeScript
/// 编译得过、Rust 编译也得过(没有哪一行提到那个新分支),只有用户
/// 点下去的那一刻才失败。把 UI 发的原样 JSON 在这儿解一遍,锁没跟上
/// 就是编译期的事,不是运行期的。
#[test]
fn every_patch_op_the_ui_sends_still_deserialises() {
let raw = r#"[
{"op":"replace","path":"/listen/gateway/bind","value":"all"},
{"op":"replace","path":"/clients/demo/max_concurrent","value":3},
{"op":"replace","path":"/clients/demo/route","value":null},
{"op":"append","path":"/clients","item":"name: a\nkey: tw-x"},
{"op":"remove","path":"/clients/a"},
{"op":"clear","path":"/clients/demo/allow"}
]"#;
let ops: Vec<tw_api::PatchOp> = serde_json::from_str(raw).expect("UI 发的 op 解不动");
assert_eq!(ops.len(), 6);
}

#[tokio::test]
async fn connecting_to_a_missing_socket_says_core_might_be_down() {
// 「Connection refused」对用户毫无意义。这里要说的是「core 可能
Expand Down
16 changes: 16 additions & 0 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,20 @@ pub fn locate_core(app: &tauri::AppHandle) -> anyhow::Result<PathBuf> {
)
}

#[tauri::command]
async fn new_key(state: tauri::State<'_, AppState>) -> Result<String, String> {
state.control.new_key().await.map_err(|e| format!("{e:#}"))
}

#[tauri::command]
async fn interfaces(state: tauri::State<'_, AppState>) -> Result<Vec<tw_api::NicView>, String> {
state
.control
.interfaces()
.await
.map_err(|e| format!("{e:#}"))
}

#[tauri::command]
async fn core_status(state: tauri::State<'_, AppState>) -> Result<tw_api::Status, String> {
// Tauri 的 invoke 用**字符串** reject,不是 Error 对象 ——
Expand Down Expand Up @@ -798,6 +812,8 @@ pub fn run() {
))
.invoke_handler(tauri::generate_handler![
core_status,
interfaces,
new_key,
core_state,
overview,
probe_upstream,
Expand Down
Loading
Loading