Skip to content

Commit 68e354f

Browse files
committed
2 parents e873092 + 6638dc5 commit 68e354f

File tree

5 files changed

+61
-6
lines changed

5 files changed

+61
-6
lines changed

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
"eslint.options": {
55
"overrideConfigFile": "./eslint.config.js"
66
},
7-
"vue.server.includeLanguages": ["vue"]
7+
"vue.server.includeLanguages": ["vue"],
8+
"rust-analyzer.linkedProjects": ["app/src-tauri/Cargo.toml"]
89
}

app/src-tauri/src/lib.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ use base64::engine::general_purpose;
55
use base64::Engine;
66

77
use tauri::Manager;
8+
use tauri::Runtime;
9+
use tauri::Url;
10+
use tauri_plugin_updater::UpdaterExt;
811

912
/// 判断文件是否存在
1013
#[tauri::command]
@@ -66,6 +69,25 @@ fn exit(code: i32) {
6669
std::process::exit(code);
6770
}
6871

72+
#[tauri::command]
73+
async fn set_update_channel<R: Runtime>(
74+
app: tauri::AppHandle<R>,
75+
channel: String,
76+
) -> Result<(), tauri_plugin_updater::Error> {
77+
println!("Setting update channel to {}", channel);
78+
app.updater_builder()
79+
.endpoints(vec![Url::parse(
80+
format!(
81+
"https://github.com/LiRenTech/project-graph/releases/{channel}/download/latest.json"
82+
)
83+
.as_str(),
84+
)?])?
85+
.build()?
86+
.check()
87+
.await?;
88+
Ok(())
89+
}
90+
6991
#[cfg_attr(mobile, tauri::mobile_entry_point)]
7092
pub fn run() {
7193
// 在 Linux 上禁用 DMA-BUF 渲染器
@@ -105,7 +127,8 @@ pub fn run() {
105127
write_file_base64,
106128
write_stdout,
107129
write_stderr,
108-
exit
130+
exit,
131+
set_update_channel
109132
])
110133
.run(tauri::generate_context!())
111134
.expect("error while running tauri application");

app/src/core/service/Settings.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export namespace Settings {
1313
// 注意:下拉菜单框必须要在语言包里面配置才能生效,否则菜单项是 Error: Option Not Found
1414
export type Settings = {
1515
language: "zh_CN" | "zh_TW" | "en";
16+
updateChannel: "latest" | "nightly";
1617
// 视觉相关
1718
lineStyle: "straight" | "bezier" | "vertical";
1819
theme: "black" | "white" | "macaron" | "morandi";
@@ -79,6 +80,7 @@ export namespace Settings {
7980
};
8081
export const defaultSettings: Settings = {
8182
language: "zh_CN",
83+
updateChannel: "latest",
8284
// 视觉相关
8385
lineStyle: "straight",
8486
theme: "black",

app/src/locales/zh_CN.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ settings:
8686
en: English
8787
zh_CN: 简体中文
8888
zh_TW: 繁體中文
89+
updateChannel:
90+
title: 更新频道
91+
options:
92+
latest: 稳定版
93+
nightly: 开发版
8994
theme:
9095
title: 舞台主题颜色
9196
options:

app/src/pages/settings/about.tsx

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { invoke } from "@tauri-apps/api/core";
12
import { check, Update } from "@tauri-apps/plugin-updater";
23
import { BookOpen, Download, MessageCircleCode } from "lucide-react";
34
import React from "react";
@@ -8,14 +9,19 @@ import icon from "../../assets/icon.png";
89
import QQ from "../../assets/qq.svg?react";
910
import versions from "../../assets/versions.json";
1011
import Button from "../../components/Button";
12+
import { Settings } from "../../core/service/Settings";
1113
import { getAppVersion } from "../../utils/otherApi";
14+
import { SettingField } from "./_field";
1215

1316
export default function About() {
1417
const [version, setVersion] = React.useState("");
1518
const [versionName, setVersionName] = React.useState("");
1619
const [versionNameEn, setVersionNameEn] = React.useState("");
1720
const [update, setUpdate] = React.useState<Update | null>(null);
1821
const [updating, setUpdating] = React.useState(false);
22+
const [newVersionFileSize, setNewVersionFileSize] = React.useState(0);
23+
const [newVersionDownloadedSize, setNewVersionDownloadedSize] = React.useState(0);
24+
const [updateChannel] = Settings.use("updateChannel");
1925
const { t, i18n } = useTranslation("about");
2026

2127
React.useEffect(() => {
@@ -34,9 +40,14 @@ export default function About() {
3440
setVersionNameEn("Unknown Version");
3541
}
3642
});
37-
check().then(setUpdate);
3843
}, []);
3944

45+
React.useEffect(() => {
46+
invoke("set_update_channel", { channel: updateChannel })
47+
.then(() => check())
48+
.then(setUpdate);
49+
}, [updateChannel]);
50+
4051
return (
4152
<div className="flex h-full">
4253
<div className="flex w-64 flex-col items-center justify-center gap-4">
@@ -52,13 +63,25 @@ export default function About() {
5263
<Button
5364
onClick={() => {
5465
setUpdating(true);
55-
update?.downloadAndInstall().then(() => {
56-
setUpdating(false);
66+
update?.downloadAndInstall((event) => {
67+
switch (event.event) {
68+
case "Started":
69+
setNewVersionFileSize(event.data.contentLength ?? 0);
70+
break;
71+
case "Progress":
72+
setNewVersionDownloadedSize((prev) => prev + (event.data.chunkLength ?? 0));
73+
break;
74+
case "Finished":
75+
setUpdating(false);
76+
break;
77+
}
5778
});
5879
}}
5980
>
6081
<Download />
61-
{updating ? t("updater.downloading") : `${t("updater.available")}: ${update.version}`}
82+
{updating
83+
? `${t("updater.downloading")}: ${((newVersionDownloadedSize / newVersionFileSize) * 100).toFixed()}%`
84+
: `${t("updater.available")}: ${update.version}`}
6285
</Button>
6386
)}
6487
<div className="flex flex-wrap justify-center gap-2">
@@ -91,6 +114,7 @@ export default function About() {
91114
</div>
92115
</div>
93116
<div className="text-panel-text flex flex-1 flex-col gap-4 overflow-auto">
117+
<SettingField icon={<Download />} settingKey="updateChannel" type="select" />
94118
<Paragraph i18nKey="intro" />
95119
<Paragraph i18nKey="ideaSources" />
96120
<Paragraph i18nKey="team" />

0 commit comments

Comments
 (0)