Compare commits
5 Commits
5
.github/workflows/ci.yml
vendored
5
.github/workflows/ci.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: CI
|
||||
name: Release CI
|
||||
|
||||
on: [push]
|
||||
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
yarn run check
|
||||
|
||||
- name: Tauri build
|
||||
uses: tauri-apps/tauri-action@v0
|
||||
uses: tauri-apps/tauri-action@b9ce5d7dc68082d21d30a60103b0ab8c5ddae3a1
|
||||
# enable cache even though failed
|
||||
continue-on-error: true
|
||||
env:
|
||||
@@ -95,6 +95,5 @@ jobs:
|
||||
|
||||
- name: Release update.json
|
||||
run: yarn run release
|
||||
continue-on-error: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "clash-verge",
|
||||
"version": "0.0.16",
|
||||
"version": "0.0.17",
|
||||
"license": "GPL-3.0",
|
||||
"scripts": {
|
||||
"dev": "cargo tauri dev",
|
||||
"build": "cargo tauri build",
|
||||
"dev": "tauri dev",
|
||||
"build": "tauri build",
|
||||
"tauri": "tauri",
|
||||
"web:dev": "vite",
|
||||
"web:build": "tsc && vite build",
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { createRequire } from "module";
|
||||
import fetch from "node-fetch";
|
||||
import { getOctokit, context } from "@actions/github";
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
const UPDATE_TAG_NAME = "updater";
|
||||
const UPDATE_JSON_FILE = "update.json";
|
||||
|
||||
/// generate update.json
|
||||
/// upload to update tag's release asset
|
||||
@@ -10,46 +11,85 @@ async function resolveRelease() {
|
||||
throw new Error("GITHUB_TOKEN is required");
|
||||
}
|
||||
|
||||
const packageJson = require("../package.json");
|
||||
const options = { owner: context.repo.owner, repo: context.repo.repo };
|
||||
const github = getOctokit(process.env.GITHUB_TOKEN);
|
||||
|
||||
const { data: tags } = await github.rest.repos.listTags({
|
||||
...options,
|
||||
per_page: 10,
|
||||
page: 1,
|
||||
});
|
||||
|
||||
// get the latest publish tag
|
||||
const tag = tags.find((t) => t.name.startsWith("v"));
|
||||
|
||||
console.log(tag);
|
||||
console.log();
|
||||
|
||||
const { data: latestRelease } = await github.rest.repos.getReleaseByTag({
|
||||
...options,
|
||||
tag: tag.name,
|
||||
});
|
||||
|
||||
const { version } = packageJson;
|
||||
const urlPrefix = "https://github.com/zzzgydi/clash-verge/releases/download";
|
||||
const updateData = {
|
||||
name: `v${version}`,
|
||||
notes: `Version ${version} is available now!!!`,
|
||||
name: tag.name,
|
||||
notes: latestRelease.body, // use the release body directly
|
||||
pub_date: new Date().toISOString(),
|
||||
platforms: {
|
||||
win64: {
|
||||
signature: "",
|
||||
url: `${urlPrefix}/v${version}/clash-verge_${version}_x64.msi.zip`,
|
||||
},
|
||||
darwin: {
|
||||
signature: "",
|
||||
url: `${urlPrefix}/v${version}/clash-verge.app.tar.gz`,
|
||||
},
|
||||
win64: { signature: "", url: "" },
|
||||
darwin: { signature: "", url: "" },
|
||||
},
|
||||
};
|
||||
|
||||
console.log(`Generating Version "${version}" update.json`);
|
||||
const promises = latestRelease.assets.map(async (asset) => {
|
||||
const { name, browser_download_url } = asset;
|
||||
|
||||
const github = getOctokit(process.env.GITHUB_TOKEN);
|
||||
|
||||
const { data: release } = await github.rest.repos.getReleaseByTag({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
tag: "updater",
|
||||
});
|
||||
const { data: assets } = await github.rest.repos.listReleaseAssets({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
release_id: release.id,
|
||||
// win64 url
|
||||
if (/\.msi\.zip$/.test(name)) {
|
||||
updateData.platforms.win64.url = browser_download_url;
|
||||
}
|
||||
// darwin url
|
||||
if (/\.app\.tar\.gz$/.test(name)) {
|
||||
updateData.platforms.darwin.url = browser_download_url;
|
||||
}
|
||||
// win64 signature
|
||||
if (/\.msi\.zip\.sig$/.test(name)) {
|
||||
updateData.platforms.win64.signature = await getSignature(
|
||||
browser_download_url
|
||||
);
|
||||
}
|
||||
// darwin signature
|
||||
if (/\.app\.tar\.gz\.sig$/.test(name)) {
|
||||
updateData.platforms.darwin.signature = await getSignature(
|
||||
browser_download_url
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
for (let asset of assets) {
|
||||
if (asset.name === "update.json") {
|
||||
await Promise.allSettled(promises);
|
||||
console.log(updateData);
|
||||
|
||||
// maybe should test the signature as well
|
||||
const { darwin, win64 } = updateData.platforms;
|
||||
if (!darwin.url) {
|
||||
console.log(`[Error]: failed to parse release for darwin`);
|
||||
delete updateData.platforms.darwin;
|
||||
}
|
||||
if (!win64.url) {
|
||||
console.log(`[Error]: failed to parse release for win64`);
|
||||
delete updateData.platforms.win64;
|
||||
}
|
||||
|
||||
// update the update.json
|
||||
const { data: updateRelease } = await github.rest.repos.getReleaseByTag({
|
||||
...options,
|
||||
tag: UPDATE_TAG_NAME,
|
||||
});
|
||||
|
||||
for (let asset of updateRelease.assets) {
|
||||
if (asset.name === UPDATE_JSON_FILE) {
|
||||
await github.rest.repos.deleteReleaseAsset({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
...options,
|
||||
asset_id: asset.id,
|
||||
});
|
||||
break;
|
||||
@@ -57,12 +97,21 @@ async function resolveRelease() {
|
||||
}
|
||||
|
||||
await github.rest.repos.uploadReleaseAsset({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
release_id: release.id,
|
||||
name: "update.json",
|
||||
...options,
|
||||
release_id: updateRelease.id,
|
||||
name: UPDATE_JSON_FILE,
|
||||
data: JSON.stringify(updateData, null, 2),
|
||||
});
|
||||
}
|
||||
|
||||
resolveRelease();
|
||||
// get the signature file content
|
||||
async function getSignature(url) {
|
||||
const response = await fetch(url, {
|
||||
method: "GET",
|
||||
headers: { "Content-Type": "application/octet-stream" },
|
||||
});
|
||||
|
||||
return response.text();
|
||||
}
|
||||
|
||||
resolveRelease().catch(console.error);
|
||||
|
||||
7
src-tauri/Cargo.lock
generated
7
src-tauri/Cargo.lock
generated
@@ -448,6 +448,7 @@ dependencies = [
|
||||
"auto-launch",
|
||||
"chrono",
|
||||
"dirs",
|
||||
"dunce",
|
||||
"log",
|
||||
"log4rs",
|
||||
"port_scanner",
|
||||
@@ -868,6 +869,12 @@ dependencies = [
|
||||
"dtoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dunce"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "453440c271cf5577fd2a40e4942540cb7d0d2f85e27c8d07dd0023c925a67541"
|
||||
|
||||
[[package]]
|
||||
name = "easy-parallel"
|
||||
version = "3.2.0"
|
||||
|
||||
@@ -14,6 +14,7 @@ tauri-build = { version = "1.0.0-rc.3", features = [] }
|
||||
|
||||
[dependencies]
|
||||
dirs = "4.0.0"
|
||||
dunce = "1.0.2"
|
||||
chrono = "0.4.19"
|
||||
serde_json = "1.0"
|
||||
serde_yaml = "0.8"
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::{
|
||||
use auto_launch::{AutoLaunch, AutoLaunchBuilder};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
use tauri::{api::path::resource_dir, async_runtime::Mutex};
|
||||
use tauri::{async_runtime::Mutex, utils::platform::current_exe};
|
||||
|
||||
/// ### `verge.yaml` schema
|
||||
#[derive(Default, Debug, Clone, Deserialize, Serialize)]
|
||||
@@ -122,13 +122,11 @@ impl Verge {
|
||||
}
|
||||
|
||||
/// init the auto launch
|
||||
pub fn init_launch(&mut self, package_info: &tauri::PackageInfo) {
|
||||
let app_name = "clash-verge";
|
||||
let app_path = get_app_path(app_name);
|
||||
let app_path = resource_dir(package_info, &tauri::Env::default())
|
||||
.unwrap()
|
||||
.join(app_path);
|
||||
let app_path = app_path.as_os_str().to_str().unwrap();
|
||||
pub fn init_launch(&mut self) {
|
||||
let app_exe = current_exe().unwrap();
|
||||
let app_exe = dunce::canonicalize(app_exe).unwrap();
|
||||
let app_name = app_exe.file_stem().unwrap().to_str().unwrap();
|
||||
let app_path = app_exe.as_os_str().to_str().unwrap();
|
||||
|
||||
let auto = AutoLaunchBuilder::new()
|
||||
.set_app_name(app_name)
|
||||
@@ -324,14 +322,3 @@ impl Verge {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Get the target app_path
|
||||
fn get_app_path(app_name: &str) -> String {
|
||||
#[cfg(target_os = "linux")]
|
||||
let ext = "";
|
||||
#[cfg(target_os = "macos")]
|
||||
let ext = "";
|
||||
#[cfg(target_os = "windows")]
|
||||
let ext = ".exe";
|
||||
String::from(app_name) + ext
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ pub fn resolve_setup(app: &App) {
|
||||
}
|
||||
|
||||
verge.init_sysproxy(clash.info.port.clone());
|
||||
verge.init_launch(app.package_info());
|
||||
verge.init_launch();
|
||||
if let Err(err) = verge.sync_launch() {
|
||||
log::error!("{}", err);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"package": {
|
||||
"productName": "clash-verge",
|
||||
"version": "0.0.16"
|
||||
"version": "0.0.17"
|
||||
},
|
||||
"build": {
|
||||
"distDir": "../dist",
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useEffect, useState } from "react";
|
||||
import { useRecoilValue } from "recoil";
|
||||
import { Box, Typography } from "@mui/material";
|
||||
import { ArrowDownward, ArrowUpward } from "@mui/icons-material";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import { ApiType } from "../../services/types";
|
||||
import { getInfomation } from "../../services/api";
|
||||
import { getVergeConfig } from "../../services/cmds";
|
||||
@@ -14,11 +15,21 @@ const LayoutTraffic = () => {
|
||||
const portValue = useRecoilValue(atomClashPort);
|
||||
const [traffic, setTraffic] = useState({ up: 0, down: 0 });
|
||||
const { canvasRef, appendData, toggleStyle } = useTrafficGraph();
|
||||
const [refresh, setRefresh] = useState({});
|
||||
|
||||
// whether hide traffic graph
|
||||
const { data } = useSWR("getVergeConfig", getVergeConfig);
|
||||
const trafficGraph = data?.traffic_graph ?? true;
|
||||
|
||||
useEffect(() => {
|
||||
let unlisten: () => void = null!;
|
||||
|
||||
// should reconnect the traffic ws
|
||||
listen("restart_clash", () => setRefresh({})).then((fn) => (unlisten = fn));
|
||||
|
||||
return () => unlisten?.();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
let ws: WebSocket | null = null;
|
||||
|
||||
@@ -34,7 +45,7 @@ const LayoutTraffic = () => {
|
||||
});
|
||||
|
||||
return () => ws?.close();
|
||||
}, [portValue]);
|
||||
}, [portValue, refresh]);
|
||||
|
||||
const [up, upUnit] = parseTraffic(traffic.up);
|
||||
const [down, downUnit] = parseTraffic(traffic.down);
|
||||
|
||||
Reference in New Issue
Block a user