mirror of
https://github.com/bolucat/Archive.git
synced 2025-09-26 20:21:35 +08:00
Update On Mon Aug 19 20:32:20 CEST 2024
This commit is contained in:
1
.github/update.log
vendored
1
.github/update.log
vendored
@@ -738,3 +738,4 @@ Update On Thu Aug 15 20:37:38 CEST 2024
|
||||
Update On Fri Aug 16 20:32:54 CEST 2024
|
||||
Update On Sat Aug 17 20:30:44 CEST 2024
|
||||
Update On Sun Aug 18 20:30:02 CEST 2024
|
||||
Update On Mon Aug 19 20:32:09 CEST 2024
|
||||
|
12
clash-meta/.github/workflows/build.yml
vendored
12
clash-meta/.github/workflows/build.yml
vendored
@@ -40,10 +40,10 @@ jobs:
|
||||
- { goos: linux, goarch: arm, goarm: '5', output: armv5 }
|
||||
- { goos: linux, goarch: arm, goarm: '6', output: armv6 }
|
||||
- { goos: linux, goarch: arm, goarm: '7', output: armv7 }
|
||||
- { goos: linux, goarch: mips, mips: hardfloat, output: mips-hardfloat }
|
||||
- { goos: linux, goarch: mips, mips: softfloat, output: mips-softfloat }
|
||||
- { goos: linux, goarch: mipsle, mips: hardfloat, output: mipsle-hardfloat }
|
||||
- { goos: linux, goarch: mipsle, mips: softfloat, output: mipsle-softfloat }
|
||||
- { goos: linux, goarch: mips, gomips: hardfloat, output: mips-hardfloat }
|
||||
- { goos: linux, goarch: mips, gomips: softfloat, output: mips-softfloat }
|
||||
- { goos: linux, goarch: mipsle, gomips: hardfloat, output: mipsle-hardfloat }
|
||||
- { goos: linux, goarch: mipsle, gomips: softfloat, output: mipsle-softfloat }
|
||||
- { goos: linux, goarch: mips64, output: mips64 }
|
||||
- { goos: linux, goarch: mips64le, output: mips64le }
|
||||
- { goos: linux, goarch: loong64, output: loong64-abi1, abi: '1' }
|
||||
@@ -219,8 +219,8 @@ jobs:
|
||||
GOOS: ${{matrix.jobs.goos}}
|
||||
GOARCH: ${{matrix.jobs.goarch}}
|
||||
GOAMD64: ${{matrix.jobs.goamd64}}
|
||||
GOARM: ${{matrix.jobs.arm}}
|
||||
GOMIPS: ${{matrix.jobs.mips}}
|
||||
GOARM: ${{matrix.jobs.goarm}}
|
||||
GOMIPS: ${{matrix.jobs.gomips}}
|
||||
run: |
|
||||
echo $CGO_ENABLED
|
||||
go build -v -tags "with_gvisor" -trimpath -ldflags "${BUILDTAG} -X 'github.com/metacubex/mihomo/constant.Version=${VERSION}' -X 'github.com/metacubex/mihomo/constant.BuildTime=${BUILDTIME}' -w -s -buildid="
|
||||
|
@@ -88,6 +88,9 @@ func ParseProxyGroup(config map[string]any, proxyMap map[string]C.Proxy, provide
|
||||
} else {
|
||||
groupOption.Proxies = append(groupOption.Proxies, AllProxies...)
|
||||
}
|
||||
if len(groupOption.Proxies) == 0 && len(groupOption.Use) == 0 {
|
||||
groupOption.Proxies = []string{"COMPATIBLE"}
|
||||
}
|
||||
}
|
||||
|
||||
if len(groupOption.Proxies) == 0 && len(groupOption.Use) == 0 {
|
||||
|
2
clash-nyanpasu/.github/workflows/ci.yml
vendored
2
clash-nyanpasu/.github/workflows/ci.yml
vendored
@@ -75,7 +75,7 @@ jobs:
|
||||
run: pnpm install --no-frozen-lockfile
|
||||
|
||||
- name: Prepare fronend
|
||||
run: pnpm web:build # Build frontend
|
||||
run: pnpm -r build # Build frontend
|
||||
- name: Prepare sidecar and resources
|
||||
run: pnpm check
|
||||
- name: Lint
|
||||
|
@@ -71,7 +71,9 @@ jobs:
|
||||
if: ${{ inputs.nightly == true }}
|
||||
run: |
|
||||
pnpm prepare:nightly
|
||||
|
||||
- name: Build UI
|
||||
run: |
|
||||
pnpm -F ui build
|
||||
- name: Tauri build
|
||||
uses: tauri-apps/tauri-action@v0
|
||||
env:
|
||||
|
@@ -99,7 +99,9 @@ jobs:
|
||||
if: ${{ inputs.nightly == true }}
|
||||
run: |
|
||||
pnpm prepare:nightly
|
||||
|
||||
- name: Build UI
|
||||
run: |
|
||||
pnpm -F ui build
|
||||
- name: Tauri build
|
||||
if: ${{ inputs.aarch64 == false }}
|
||||
uses: tauri-apps/tauri-action@v0
|
||||
|
@@ -78,6 +78,9 @@ jobs:
|
||||
if: ${{ inputs.nightly == true }}
|
||||
run: |
|
||||
pnpm prepare:nightly --nsis
|
||||
- name: Build UI
|
||||
run: |
|
||||
pnpm -F ui build
|
||||
|
||||
- name: Tauri build
|
||||
uses: tauri-apps/tauri-action@v0
|
||||
|
@@ -15,8 +15,8 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
importOrder: [
|
||||
"^@ui/(.*)$",
|
||||
"^@interface/(.*)$",
|
||||
"^@nyanpasu/ui/(.*)$",
|
||||
"^@nyanpasu/interface/(.*)$",
|
||||
"^@/(.*)$",
|
||||
"^@(.*)$",
|
||||
"^[./]",
|
||||
|
511
clash-nyanpasu/backend/Cargo.lock
generated
511
clash-nyanpasu/backend/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -43,7 +43,7 @@ delay_timer = "0.11.5"
|
||||
parking_lot = { version = "0.12.1" }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
reqwest = { version = "0.11", features = ["json", "rustls-tls"] }
|
||||
reqwest = { version = "0.12", features = ["json", "rustls-tls", "stream"] }
|
||||
relative-path = "1.9"
|
||||
tauri = { version = "1.5.4", features = [
|
||||
"fs-all",
|
||||
@@ -67,7 +67,7 @@ wry = { version = "0.24.6" }
|
||||
semver = "1.0"
|
||||
zip = "2.0.0"
|
||||
zip-extensions = "0.8.0"
|
||||
gunzip = { version = "0.1.0", git = "https://github.com/TechHara/gunzip.git" }
|
||||
flate2 = "1.0"
|
||||
tempfile = "3.9.0"
|
||||
glob = "0.3.1"
|
||||
async-trait = "0.1.77"
|
||||
|
@@ -115,6 +115,8 @@ impl UpdaterBuilder {
|
||||
download_url.set_path(&download_path);
|
||||
let download_url = crate::utils::candy::parse_gh_url(&mirror, download_url.as_str())?;
|
||||
let file = tokio::fs::File::create(temp_dir.path().join(&artifact)).await?;
|
||||
tracing::debug!("downloader url: {}", download_url);
|
||||
tracing::debug!("downloader file: {:?}", file);
|
||||
let (tx, rx) = tokio::sync::mpsc::channel::<DownloaderState>(1);
|
||||
let callback: Box<dyn Fn(DownloaderState) + Send + Sync> = Box::new(move |state| {
|
||||
let tx = tx.clone();
|
||||
@@ -146,6 +148,7 @@ impl UpdaterBuilder {
|
||||
|
||||
impl Updater {
|
||||
fn dispatch_state(&self, state: UpdaterState) {
|
||||
tracing::debug!("dispatching updater state: {:?}", state);
|
||||
let mut inner = self.inner.write();
|
||||
inner.state = state;
|
||||
}
|
||||
@@ -162,8 +165,8 @@ impl Updater {
|
||||
match artifact {
|
||||
fname if fname.ends_with(".gz") => {
|
||||
tracing::debug!("decompressing gz file");
|
||||
let mut decompressor = gunzip::Decompressor::new(tmp_file, true);
|
||||
std::io::copy(&mut decompressor, &mut buff)?;
|
||||
let mut decoder = flate2::read::GzDecoder::new(&mut tmp_file);
|
||||
std::io::copy(&mut decoder, &mut buff)?;
|
||||
}
|
||||
fname if fname.ends_with(".zip") => {
|
||||
tracing::debug!("decompressing zip file");
|
||||
@@ -193,7 +196,11 @@ impl Updater {
|
||||
Ok::<_, anyhow::Error>(buff)
|
||||
})
|
||||
.await??;
|
||||
let tmp_core = self.temp_dir.path().join(self.core_type.to_string());
|
||||
let tmp_core = self.temp_dir.path().join(format!(
|
||||
"{}{}",
|
||||
self.core_type,
|
||||
std::env::consts::EXE_SUFFIX
|
||||
));
|
||||
tracing::debug!("writing core to {:?} ({} bytes)", tmp_core, buff.len());
|
||||
let mut core_file = tokio::fs::File::create(&tmp_core).await?;
|
||||
tokio::io::copy(&mut buff.as_slice(), &mut core_file).await?;
|
||||
@@ -222,7 +229,11 @@ impl Updater {
|
||||
let core_dir = core_dir.parent().ok_or(anyhow!("failed to get core dir"))?;
|
||||
let target_core = core_dir.join(target_core);
|
||||
tracing::debug!("copying core to {:?}", target_core);
|
||||
let tmp_core_path = self.temp_dir.path().join(&self.artifact);
|
||||
let tmp_core_path = self.temp_dir.path().join(format!(
|
||||
"{}{}",
|
||||
self.core_type,
|
||||
std::env::consts::EXE_SUFFIX
|
||||
));
|
||||
match tokio::fs::copy(tmp_core_path.clone(), target_core.clone()).await {
|
||||
Ok(_) => {}
|
||||
Err(err) => {
|
||||
|
@@ -225,6 +225,11 @@ pub async fn url_delay_test(url: &str, expected_status: u16) -> CmdResult<Option
|
||||
Ok(crate::utils::net::url_delay_test(url, expected_status).await)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_ipsb_asn() -> CmdResult<Mapping> {
|
||||
wrap_err!(crate::utils::net::get_ipsb_asn().await)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[tracing_attributes::instrument]
|
||||
pub async fn patch_clash_config(payload: Mapping) -> CmdResult {
|
||||
|
@@ -240,6 +240,7 @@ fn main() -> std::io::Result<()> {
|
||||
ipc::is_tray_icon_set,
|
||||
ipc::get_core_status,
|
||||
ipc::url_delay_test,
|
||||
ipc::get_ipsb_asn,
|
||||
]);
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
|
@@ -1,5 +1,7 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use serde_yaml::Mapping;
|
||||
|
||||
use super::candy::get_reqwest_client;
|
||||
|
||||
#[tracing_attributes::instrument]
|
||||
@@ -20,3 +22,15 @@ pub async fn url_delay_test(url: &str, expected_status: u16) -> Option<u64> {
|
||||
}
|
||||
Some(tick.elapsed().as_millis() as u64)
|
||||
}
|
||||
|
||||
#[tracing_attributes::instrument]
|
||||
pub async fn get_ipsb_asn() -> anyhow::Result<Mapping> {
|
||||
let client = get_reqwest_client()?;
|
||||
let response = client
|
||||
.get("https://api.ip.sb/geoip")
|
||||
.send()
|
||||
.await?
|
||||
.error_for_status()?;
|
||||
let data: Mapping = response.json().await?;
|
||||
Ok(data)
|
||||
}
|
||||
|
@@ -1,8 +1,15 @@
|
||||
{
|
||||
"name": "@nyanpasu/interface",
|
||||
"version": "0.1.0",
|
||||
"main": "index.ts",
|
||||
"module": "index.ts",
|
||||
"main": "dist/src/index.js",
|
||||
"types": "dist/src/index.d.ts",
|
||||
"require": {
|
||||
".": "dist/src/index.js"
|
||||
},
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "1.6.0",
|
||||
"ahooks": "3.8.1",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import useSWR from "swr";
|
||||
import { ClashConfig, Profile } from "@/index";
|
||||
import * as tauri from "@/service/tauri";
|
||||
import { ClashConfig, Profile } from "..";
|
||||
import { Clash, clash } from "../service/clash";
|
||||
|
||||
/**
|
@@ -1,7 +1,7 @@
|
||||
import { ofetch } from "ofetch";
|
||||
import useSWR from "swr";
|
||||
import { getIpsbASN } from "@/service";
|
||||
|
||||
interface IPSBResponse {
|
||||
export interface IPSBResponse {
|
||||
organization: string;
|
||||
longitude: number;
|
||||
timezone: string;
|
||||
@@ -17,8 +17,5 @@ interface IPSBResponse {
|
||||
}
|
||||
|
||||
export const useIPSB = () => {
|
||||
return useSWR(
|
||||
"https://api.ip.sb/geoip",
|
||||
async () => await ofetch<IPSBResponse>("https://api.ip.sb/geoip"),
|
||||
);
|
||||
return useSWR("https://api.ip.sb/geoip", () => getIpsbASN());
|
||||
};
|
@@ -1,3 +1,4 @@
|
||||
import { IPSBResponse } from "@/openapi";
|
||||
import { invoke } from "@tauri-apps/api/tauri";
|
||||
import { ManifestVersion } from "./core";
|
||||
import {
|
||||
@@ -244,3 +245,5 @@ export const urlDelayTest = async (url: string, expectedStatus: number) => {
|
||||
expectedStatus,
|
||||
});
|
||||
};
|
||||
|
||||
export const getIpsbASN = async () => invoke<IPSBResponse>("get_ipsb_asn");
|
@@ -15,11 +15,12 @@
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"declaration": true,
|
||||
"composite": true,
|
||||
"declaration": true,
|
||||
"paths": {
|
||||
"@/*": ["./*"],
|
||||
"@/*": ["./src/*"],
|
||||
},
|
||||
"outDir": "./dist",
|
||||
},
|
||||
"include": ["./"],
|
||||
"include": ["src"],
|
||||
}
|
||||
|
@@ -27,7 +27,7 @@
|
||||
"country-code-emoji": "2.3.0",
|
||||
"dayjs": "1.11.12",
|
||||
"framer-motion": "12.0.0-alpha.0",
|
||||
"i18next": "23.12.3",
|
||||
"i18next": "23.14.0",
|
||||
"jotai": "2.9.3",
|
||||
"material-react-table": "2.13.1",
|
||||
"monaco-editor": "0.50.0",
|
||||
@@ -39,26 +39,26 @@
|
||||
"react-hook-form-mui": "7.0.1",
|
||||
"react-i18next": "15.0.1",
|
||||
"react-markdown": "9.0.1",
|
||||
"react-router-dom": "6.26.0",
|
||||
"react-router-dom": "6.26.1",
|
||||
"react-split-grid": "1.0.4",
|
||||
"swr": "2.2.5",
|
||||
"virtua": "0.33.6"
|
||||
"virtua": "0.33.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@emotion/babel-plugin": "11.12.0",
|
||||
"@emotion/react": "11.13.0",
|
||||
"@iconify/json": "2.2.237",
|
||||
"@iconify/json": "2.2.238",
|
||||
"@types/react": "18.3.3",
|
||||
"@types/react-dom": "18.3.0",
|
||||
"@vitejs/plugin-react": "4.3.1",
|
||||
"@vitejs/plugin-react-swc": "3.7.0",
|
||||
"clsx": "2.1.1",
|
||||
"sass": "1.77.8",
|
||||
"shiki": "1.13.0",
|
||||
"shiki": "1.14.1",
|
||||
"tailwindcss-textshadow": "2.1.3",
|
||||
"unplugin-auto-import": "0.18.2",
|
||||
"unplugin-icons": "0.19.2",
|
||||
"vite": "5.4.0",
|
||||
"vite": "5.4.1",
|
||||
"vite-plugin-monaco-editor": "1.1.3",
|
||||
"vite-plugin-sass-dts": "1.3.25",
|
||||
"vite-plugin-svgr": "4.2.0",
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import { Allotment } from "allotment";
|
||||
import "allotment/dist/style.css";
|
||||
import { ReactNode } from "react";
|
||||
import getSystem from "@/utils/get-system";
|
||||
import { alpha, useTheme } from "@mui/material";
|
||||
import Paper from "@mui/material/Paper";
|
||||
import { appWindow } from "@tauri-apps/api/window";
|
||||
import "allotment/dist/style.css";
|
||||
import { ReactNode } from "react";
|
||||
import { LayoutControl } from "../layout/layout-control";
|
||||
import styles from "./app-container.module.scss";
|
||||
import AppDrawer from "./app-drawer";
|
||||
@@ -40,7 +40,7 @@ export const AppContainer = ({
|
||||
e.preventDefault();
|
||||
}}
|
||||
>
|
||||
{isDrawer && <AppDrawer data-windrag isDrawer />}
|
||||
{isDrawer && <AppDrawer data-windrag />}
|
||||
|
||||
<Allotment separator proportionalLayout={false}>
|
||||
{!isDrawer && (
|
||||
|
@@ -72,7 +72,7 @@ export const AppDrawer = () => {
|
||||
type: "tween",
|
||||
}}
|
||||
>
|
||||
<DrawerContent isDrawer className="max-w-64" />
|
||||
<DrawerContent className="max-w-64" />
|
||||
</motion.div>
|
||||
</div>
|
||||
</AnimatePresence>
|
||||
|
@@ -1,11 +1,12 @@
|
||||
import { cloneElement, FC } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import parseTraffic from "@/utils/parse-traffic";
|
||||
import { SvgIconComponent } from "@mui/icons-material";
|
||||
import { type SvgIconComponent } from "@mui/icons-material";
|
||||
import { Paper } from "@mui/material";
|
||||
import { Sparkline } from "@nyanpasu/ui";
|
||||
import { cn, Sparkline } from "@nyanpasu/ui";
|
||||
|
||||
export interface DatalineProps {
|
||||
className?: string;
|
||||
data: number[];
|
||||
icon: SvgIconComponent;
|
||||
title: string;
|
||||
@@ -19,15 +20,17 @@ export const Dataline: FC<DatalineProps> = ({
|
||||
title,
|
||||
total,
|
||||
type,
|
||||
className,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Paper className="relative !rounded-3xl">
|
||||
<Paper className={cn("relative !rounded-3xl", className)}>
|
||||
<Sparkline data={data} className="rounded-3xl" />
|
||||
|
||||
<div className="absolute top-0 flex h-full flex-col justify-between gap-4 p-4">
|
||||
<div className="flex items-center gap-2">
|
||||
{/* @ts-expect-error icon should be cloneable */}
|
||||
{cloneElement(icon)}
|
||||
|
||||
<div className="font-bold">{title}</div>
|
||||
|
@@ -11,7 +11,7 @@ import {
|
||||
ListItemText,
|
||||
} from "@mui/material";
|
||||
import { getServerPort, useClashCore } from "@nyanpasu/interface";
|
||||
import LazyImage from "@nyanpasu/ui/materialYou/components/lazyImage";
|
||||
import { LazyImage } from "@nyanpasu/ui";
|
||||
|
||||
const IconRender = memo(function IconRender({ icon }: { icon: string }) {
|
||||
const {
|
||||
|
@@ -5,6 +5,7 @@ import {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useImperativeHandle,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
useTransition,
|
||||
@@ -59,28 +60,34 @@ export const NodeList = forwardRef(function NodeList({}, ref) {
|
||||
}
|
||||
}
|
||||
}, [
|
||||
data?.global,
|
||||
data?.groups,
|
||||
getCurrentMode.global,
|
||||
proxyGroup.selector,
|
||||
getCurrentMode,
|
||||
proxyGroupSort,
|
||||
setGroup,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
sortGroup();
|
||||
}, [sortGroup]);
|
||||
|
||||
const { column } = useBreakpoint({
|
||||
sm: 1,
|
||||
md: 1,
|
||||
lg: 2,
|
||||
xl: 3,
|
||||
default: 4,
|
||||
});
|
||||
const breakpoint = useBreakpoint();
|
||||
const column = useMemo(() => {
|
||||
switch (breakpoint) {
|
||||
case "xs":
|
||||
case "sm":
|
||||
return 1;
|
||||
case "md":
|
||||
case "lg":
|
||||
return 2;
|
||||
case "xl":
|
||||
return 4;
|
||||
}
|
||||
}, [breakpoint]);
|
||||
|
||||
const [renderList, setRenderList] = useState<RenderClashProxy[][]>([]);
|
||||
|
||||
const updateRenderList = () => {
|
||||
const updateRenderList = useCallback(() => {
|
||||
if (!group?.all) return;
|
||||
|
||||
const nodeNames: string[] = [];
|
||||
@@ -114,13 +121,13 @@ export const NodeList = forwardRef(function NodeList({}, ref) {
|
||||
);
|
||||
|
||||
setRenderList(list);
|
||||
};
|
||||
}, [column, group?.all]);
|
||||
|
||||
useEffect(() => {
|
||||
startTransition(() => {
|
||||
updateRenderList();
|
||||
});
|
||||
}, [group?.all, column]);
|
||||
}, [group?.all, column, updateRenderList]);
|
||||
|
||||
const hendleClick = (node: string) => {
|
||||
if (!getCurrentMode.global) {
|
||||
|
@@ -103,7 +103,7 @@ const CardProgress = ({
|
||||
|
||||
<div className="truncate">
|
||||
{calcProgress(data).toFixed(0)}%{""}
|
||||
<span>({parseTraffic(data?.downloader.speed)}/s)</span>
|
||||
<span>({parseTraffic(data?.downloader.speed || 0)}/s)</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
@@ -137,7 +137,7 @@ export const ClashCoreItem = ({
|
||||
|
||||
const { palette } = useTheme();
|
||||
|
||||
const { updateCore } = useNyanpasu();
|
||||
const { updateCore, getClashCore } = useNyanpasu();
|
||||
|
||||
const haveNewVersion = data.latest ? data.latest !== data.version : false;
|
||||
|
||||
@@ -172,6 +172,8 @@ export const ClashCoreItem = ({
|
||||
}, 100);
|
||||
});
|
||||
|
||||
getClashCore.mutate();
|
||||
|
||||
message(`Successfully update core ${data.name}`, {
|
||||
type: "info",
|
||||
title: t("Success"),
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { ReactNode } from "react";
|
||||
import { ReactElement, ReactNode } from "react";
|
||||
import Marquee from "react-fast-marquee";
|
||||
import DeleteRounded from "@mui/icons-material/DeleteRounded";
|
||||
import EditRounded from "@mui/icons-material/EditRounded";
|
||||
@@ -28,7 +28,7 @@ export const renderChip = (
|
||||
labels: {
|
||||
[label: string]: string | number | undefined;
|
||||
},
|
||||
): (string | JSX.Element)[] => {
|
||||
): (string | ReactElement)[] => {
|
||||
return string.split(/(%[^&?]+)/).map((part, index) => {
|
||||
if (part.startsWith("%")) {
|
||||
const label = labels[part.replace("%", "")];
|
||||
|
@@ -1,9 +1,10 @@
|
||||
import clsx from "clsx";
|
||||
import { CSSProperties, useRef, useState } from "react";
|
||||
import { parseHotkey } from "@/utils/parse-hotkey";
|
||||
import { DeleteRounded } from "@mui/icons-material";
|
||||
import { alpha, IconButton, useTheme } from "@mui/material";
|
||||
import Kbd from "@nyanpasu/ui/materialYou/components/kbd";
|
||||
import type {} from "@mui/material/themeCssVarsAugmentation";
|
||||
import clsx from "clsx";
|
||||
import { CSSProperties, useRef, useState } from "react";
|
||||
import { Kbd } from "@nyanpasu/ui";
|
||||
import styles from "./hotkey-input.module.scss";
|
||||
|
||||
export interface Props extends React.HTMLAttributes<HTMLInputElement> {
|
||||
|
@@ -58,7 +58,7 @@ const FieldsControl = ({
|
||||
close="Close"
|
||||
onClose={() => setOpen(false)}
|
||||
divider
|
||||
contentSx={{ overflow: "auto" }}
|
||||
contentStyle={{ overflow: "auto" }}
|
||||
>
|
||||
<Box display="flex" flexDirection="column" gap={1}>
|
||||
{disabled && <Typography>Clash Nyanpasu Control Fields.</Typography>}
|
||||
|
@@ -113,7 +113,7 @@ export const SettingClashWeb = () => {
|
||||
}}
|
||||
ok="Submit"
|
||||
close="Close"
|
||||
contentSx={{ overflow: editString ? "auto" : "hidden" }}
|
||||
contentStyle={{ overflow: editString ? "auto" : "hidden" }}
|
||||
divider
|
||||
>
|
||||
<Box display="flex" flexDirection="column" gap={1}>
|
||||
|
@@ -1,77 +0,0 @@
|
||||
import useSWR, { mutate } from "swr";
|
||||
// import { getProxies, updateProxy } from "@/services/api";
|
||||
import { updateProxy } from "@/services/api";
|
||||
import {
|
||||
getProfiles,
|
||||
getProxies,
|
||||
patchProfile,
|
||||
patchProfilesConfig,
|
||||
} from "@/services/cmds";
|
||||
|
||||
export const useProfiles = () => {
|
||||
const { data: profiles, mutate: mutateProfiles } = useSWR(
|
||||
"getProfiles",
|
||||
getProfiles,
|
||||
);
|
||||
|
||||
const patchProfiles = async (value: Partial<IProfilesConfig>) => {
|
||||
await patchProfilesConfig(value);
|
||||
mutateProfiles();
|
||||
};
|
||||
|
||||
const patchCurrent = async (value: Partial<IProfileItem>) => {
|
||||
if (profiles?.current) {
|
||||
await patchProfile(profiles.current, value);
|
||||
mutateProfiles();
|
||||
}
|
||||
};
|
||||
|
||||
// 根据selected的节点选择
|
||||
const activateSelected = async () => {
|
||||
const proxiesData = await getProxies();
|
||||
console.log(proxiesData);
|
||||
const profileData = await getProfiles();
|
||||
|
||||
if (!profileData || !proxiesData) return;
|
||||
|
||||
const current = profileData.items?.find(
|
||||
(e) => e && e.uid === profileData.current,
|
||||
);
|
||||
|
||||
if (!current) return;
|
||||
|
||||
// init selected array
|
||||
const { selected = [] } = current;
|
||||
const selectedMap = Object.fromEntries(
|
||||
selected.map((each) => [each.name!, each.now!]),
|
||||
);
|
||||
|
||||
let hasChange = false;
|
||||
|
||||
const newSelected: typeof selected = [];
|
||||
const { global, groups } = proxiesData;
|
||||
|
||||
[global, ...groups].forEach(({ type, name, now }) => {
|
||||
if (!now || type !== "Selector") return;
|
||||
if (selectedMap[name] != null && selectedMap[name] !== now) {
|
||||
hasChange = true;
|
||||
updateProxy(name, selectedMap[name]);
|
||||
}
|
||||
newSelected.push({ name, now: selectedMap[name] });
|
||||
});
|
||||
|
||||
if (hasChange) {
|
||||
patchProfile(profileData.current!, { selected: newSelected });
|
||||
mutate("getProxies", getProxies());
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
profiles,
|
||||
current: profiles?.items?.find((p) => p && p.uid === profiles.current),
|
||||
activateSelected,
|
||||
patchProfiles,
|
||||
patchCurrent,
|
||||
mutateProfiles,
|
||||
};
|
||||
};
|
@@ -11,6 +11,7 @@ import {
|
||||
useCustomTheme,
|
||||
} from "@/components/layout/use-custom-theme";
|
||||
import LogProvider from "@/components/logs/log-provider";
|
||||
import { atomIsDrawer } from "@/store";
|
||||
import { classNames } from "@/utils";
|
||||
import { useTheme } from "@mui/material";
|
||||
import { Experimental_CssVarsProvider as CssVarsProvider } from "@mui/material/styles";
|
||||
@@ -23,7 +24,6 @@ import { useAtom } from "jotai";
|
||||
import { useEffect } from "react";
|
||||
import { FallbackProps } from "react-error-boundary";
|
||||
import { SWRConfig } from "swr";
|
||||
import { atomIsDrawer } from "@/store";
|
||||
import styles from "./_app.module.scss";
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
@@ -31,13 +31,13 @@ dayjs.extend(relativeTime);
|
||||
export default function App() {
|
||||
const { theme } = useCustomTheme();
|
||||
|
||||
const { column } = useBreakpoint();
|
||||
const breakpoint = useBreakpoint();
|
||||
|
||||
const [isDrawer, setIsDrawer] = useAtom(atomIsDrawer);
|
||||
|
||||
useEffect(() => {
|
||||
setIsDrawer(Boolean(column === 1));
|
||||
}, [column]);
|
||||
setIsDrawer(breakpoint === "sm" || breakpoint === "xs");
|
||||
}, [breakpoint, setIsDrawer]);
|
||||
|
||||
useMount(() => {
|
||||
import("@tauri-apps/api/window")
|
||||
|
@@ -1,10 +1,14 @@
|
||||
import { useThrottle } from "ahooks";
|
||||
import { useState } from "react";
|
||||
import { lazy, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { SearchTermCtx } from "@/components/connections/connection-search-term";
|
||||
import HeaderSearch from "@/components/connections/header-search";
|
||||
import { BasePage } from "@nyanpasu/ui";
|
||||
|
||||
const Component = lazy(
|
||||
() => import("@/components/connections/connection-page"),
|
||||
);
|
||||
|
||||
export const Connections = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -25,8 +29,9 @@ export const Connections = () => {
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
children={() => import("@/components/connections/connection-page")}
|
||||
></BasePage>
|
||||
>
|
||||
<Component />
|
||||
</BasePage>
|
||||
</SearchTermCtx.Provider>
|
||||
);
|
||||
};
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Generouted, changes to this file will be overriden
|
||||
/* eslint-disable */
|
||||
|
||||
import { components, hooks, utils } from '@generouted/react-router/client'
|
||||
import { components, hooks, utils } from "@generouted/react-router/client";
|
||||
|
||||
export type Path =
|
||||
| `/connections`
|
||||
@@ -11,14 +11,16 @@ export type Path =
|
||||
| `/providers`
|
||||
| `/proxies`
|
||||
| `/rules`
|
||||
| `/settings`
|
||||
| `/settings`;
|
||||
|
||||
export type Params = {
|
||||
|
||||
}
|
||||
export type Params = {};
|
||||
|
||||
export type ModalPath = never
|
||||
export type ModalPath = never;
|
||||
|
||||
export const { Link, Navigate } = components<Path, Params>()
|
||||
export const { useModals, useNavigate, useParams } = hooks<Path, Params, ModalPath>()
|
||||
export const { redirect } = utils<Path, Params>()
|
||||
export const { Link, Navigate } = components<Path, Params>();
|
||||
export const { useModals, useNavigate, useParams } = hooks<
|
||||
Path,
|
||||
Params,
|
||||
ModalPath
|
||||
>();
|
||||
export const { redirect } = utils<Path, Params>();
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { atom } from "jotai";
|
||||
import type { VergeConfig } from "@nyanpasu/interface/service/types";
|
||||
import type { VergeConfig } from "@nyanpasu/interface";
|
||||
|
||||
export const coreTypeAtom =
|
||||
atom<NonNullable<VergeConfig["clash_core"]>>("mihomo");
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { MUI_BREAKPOINTS } from "@nyanpasu/ui/materialYou/createTheme";
|
||||
import { MUI_BREAKPOINTS } from "@nyanpasu/ui";
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
/* eslint-disable @typescript-eslint/no-require-imports */
|
||||
|
@@ -14,14 +14,15 @@
|
||||
"moduleResolution": "Node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "preserve",
|
||||
"composite": true,
|
||||
"paths": {
|
||||
"@/*": ["src/*"],
|
||||
"@/*": ["./src/*"],
|
||||
"~/*": ["./*"],
|
||||
},
|
||||
"jsxImportSource": "@emotion/react",
|
||||
"types": ["unplugin-icons/types/react"],
|
||||
},
|
||||
"include": ["./src", "./auto-imports.d.ts"],
|
||||
"references": [{ "path": "../interface/tsconfig.json" }],
|
||||
"include": ["src", "./auto-imports.d.ts"],
|
||||
"references": [{ "path": "../interface" }, { "path": "../ui" }],
|
||||
}
|
||||
|
@@ -69,6 +69,12 @@ export default defineConfig(({ command }) => {
|
||||
monaco({ languageWorkers: ["editorWorkerService", "typescript"] }),
|
||||
isDev && devtools(),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
"@nyanpasu/ui": path.resolve("../ui/src"),
|
||||
"@nyanpasu/interface": path.resolve("../interface/src"),
|
||||
},
|
||||
},
|
||||
optimizeDeps: {
|
||||
entries: ["./src/pages/**/*.tsx", "./src/main.tsx"],
|
||||
include: ["@emotion/styled"],
|
||||
|
@@ -1,4 +0,0 @@
|
||||
export * from "./materialYou";
|
||||
export * from "./hooks";
|
||||
export * from "./chart";
|
||||
export * from "./utils";
|
@@ -1,8 +1,18 @@
|
||||
{
|
||||
"name": "@nyanpasu/ui",
|
||||
"version": "0.1.0",
|
||||
"main": "index.ts",
|
||||
"module": "index.ts",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./dist/index.js"
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "vite build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@material/material-color-utilities": "0.3.0",
|
||||
"@mui/icons-material": "5.16.7",
|
||||
@@ -13,13 +23,16 @@
|
||||
"@tauri-apps/api": "1.6.0",
|
||||
"@types/d3": "7.4.3",
|
||||
"@types/react": "18.3.3",
|
||||
"@vitejs/plugin-react": "4.3.1",
|
||||
"ahooks": "3.8.1",
|
||||
"d3": "7.9.0",
|
||||
"framer-motion": "12.0.0-alpha.0",
|
||||
"react": "18.3.1",
|
||||
"react-error-boundary": "4.0.13",
|
||||
"react-i18next": "15.0.1",
|
||||
"react-use": "^17.5.1"
|
||||
"react-use": "17.5.1",
|
||||
"vite": "5.4.1",
|
||||
"vite-tsconfig-paths": "5.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@emotion/react": "11.13.0",
|
||||
@@ -28,6 +41,7 @@
|
||||
"d3-interpolate-path": "2.3.0",
|
||||
"sass": "1.77.8",
|
||||
"tailwind-merge": "2.5.2",
|
||||
"typescript-plugin-css-modules": "5.1.0"
|
||||
"typescript-plugin-css-modules": "5.1.0",
|
||||
"vite-plugin-dts": "4.0.3"
|
||||
}
|
||||
}
|
||||
|
@@ -11,13 +11,13 @@ type Platform =
|
||||
| "cygwin"
|
||||
| "netbsd";
|
||||
|
||||
declare const OS_PLATFORM: Platform;
|
||||
declare const OS_PLATFORM: Platform | undefined;
|
||||
|
||||
// get the system os
|
||||
// according to UA
|
||||
export function getSystem() {
|
||||
const ua = navigator.userAgent;
|
||||
const platform = OS_PLATFORM;
|
||||
const ua = typeof window === "undefined" ? "" : window.navigator?.userAgent;
|
||||
const platform = typeof OS_PLATFORM !== "undefined" ? OS_PLATFORM : "unknown";
|
||||
|
||||
if (ua.includes("Mac OS X") || platform === "darwin") return "macos";
|
||||
|
@@ -1,8 +1,7 @@
|
||||
import { useAsyncEffect } from "ahooks";
|
||||
import { useEffect, useState } from "react";
|
||||
import { createBreakpoint } from "react-use";
|
||||
import { MUI_BREAKPOINTS } from "@/materialYou";
|
||||
import { appWindow } from "@tauri-apps/api/window";
|
||||
import { MUI_BREAKPOINTS } from "../materialYou";
|
||||
|
||||
export type Breakpoint = "xs" | "sm" | "md" | "lg" | "xl";
|
||||
|
||||
@@ -29,7 +28,6 @@ export const useBreakpointValue = <T>(
|
||||
defaultValue?: T,
|
||||
): T => {
|
||||
const currentBreakpoint = useBreakpoint();
|
||||
|
||||
const calculateValue = (): T => {
|
||||
const value = values[currentBreakpoint];
|
||||
|
||||
@@ -53,6 +51,7 @@ export const useBreakpointValue = <T>(
|
||||
const [result, setResult] = useState<T>(calculateValue);
|
||||
|
||||
useAsyncEffect(async () => {
|
||||
const { appWindow } = await import("@tauri-apps/api/window");
|
||||
if (!(await appWindow.isMinimized())) {
|
||||
setResult(calculateValue);
|
||||
}
|
9
clash-nyanpasu/frontend/ui/src/index.ts
Normal file
9
clash-nyanpasu/frontend/ui/src/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
if (typeof window === "undefined") {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
global.window = {} as any;
|
||||
}
|
||||
|
||||
export * from "./chart";
|
||||
export * from "./hooks";
|
||||
export * from "./materialYou";
|
||||
export * from "./utils";
|
@@ -74,7 +74,7 @@ export const BaseDialog = ({
|
||||
y: clickPosition?.y ?? 0,
|
||||
});
|
||||
}
|
||||
}, [open]);
|
||||
}, [clickPosition?.x, clickPosition?.y, open]);
|
||||
|
||||
const handleClose = () => {
|
||||
if (onClose) {
|
||||
@@ -106,7 +106,7 @@ export const BaseDialog = ({
|
||||
} else {
|
||||
handleClose();
|
||||
}
|
||||
}, [open]);
|
||||
}, [cancelMounted, handleClose, open]);
|
||||
|
||||
return (
|
||||
<AnimatePresence initial={false}>
|
@@ -1,10 +1,10 @@
|
||||
import { motion } from "framer-motion";
|
||||
import { CSSProperties, FC, ReactNode, Ref, Suspense } from "react";
|
||||
import { cn } from "@/utils";
|
||||
import * as ScrollArea from "@radix-ui/react-scroll-area";
|
||||
import { BaseErrorBoundary } from "./baseErrorBoundary";
|
||||
import Header from "./header";
|
||||
import "./style.scss";
|
||||
import { motion } from "framer-motion";
|
||||
import { cn } from "@/utils";
|
||||
import * as ScrollArea from "@radix-ui/react-scroll-area";
|
||||
|
||||
interface BasePageProps {
|
||||
title?: ReactNode;
|
@@ -5,6 +5,7 @@ export * from "./expand";
|
||||
export * from "./expandMore";
|
||||
export * from "./floatingButton";
|
||||
export * from "./item";
|
||||
export * from "./kbd";
|
||||
export * from "./lazyImage";
|
||||
export * from "./loadingButton";
|
||||
export * from "./loadingSwitch";
|
@@ -1,4 +1,4 @@
|
||||
import clsx from "clsx";
|
||||
import { cn } from "@/utils";
|
||||
import { useTheme } from "@mui/material";
|
||||
import styles from "./index.module.scss";
|
||||
|
||||
@@ -7,11 +7,11 @@ export type Props = React.DetailedHTMLProps<
|
||||
HTMLElement
|
||||
>;
|
||||
|
||||
export default function Kbd({ className, children, ...rest }: Props) {
|
||||
export function Kbd({ className, children, ...rest }: Props) {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<kbd
|
||||
className={clsx(
|
||||
className={cn(
|
||||
styles.kbd,
|
||||
theme.palette.mode === "dark" && styles.dark,
|
||||
className,
|
@@ -5,7 +5,7 @@ export interface LazyImageProps
|
||||
extends React.ImgHTMLAttributes<HTMLImageElement> {
|
||||
loadingClassName?: string;
|
||||
}
|
||||
export default function LazyImage(props: LazyImageProps) {
|
||||
export function LazyImage(props: LazyImageProps) {
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
return (
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user