Style: UI improvement & 1.4.6 ready

This commit is contained in:
wonfen 2024-01-09 13:57:53 +08:00
parent e743478a4d
commit 7a030b9224
12 changed files with 182 additions and 182 deletions

View File

@ -41,18 +41,18 @@ A Clash Meta GUI based on <a href="https://github.com/tauri-apps/tauri">Tauri</a
Download from [release](https://github.com/clash-verge-rev/clash-verge-rev/releases). Supports Windows (x64/x86), Linux (x64/arm64) and macOS 10.15+ (intel/apple). Download from [release](https://github.com/clash-verge-rev/clash-verge-rev/releases). Supports Windows (x64/x86), Linux (x64/arm64) and macOS 10.15+ (intel/apple).
- [Windows x64](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.5/Clash.Verge_1.4.5_x64-setup.exe) - [Windows x64](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.6/Clash.Verge_1.4.6_x64-setup.exe)
- [Windows x86](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.5/Clash.Verge_1.4.5_x86-setup.exe) - [Windows x86](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.6/Clash.Verge_1.4.6_x86-setup.exe)
- [Windows arm64](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.5/Clash.Verge_1.4.5_arm64-setup.exe) - [Windows arm64](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.6/Clash.Verge_1.4.6_arm64-setup.exe)
- [macOS intel](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.5/Clash.Verge_1.4.5_x64.dmg) - [macOS intel](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.6/Clash.Verge_1.4.6_x64.dmg)
- [macOS apple](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.5/Clash.Verge_1.4.5_aarch64.dmg) - [macOS apple](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.6/Clash.Verge_1.4.6_aarch64.dmg)
- [Linux x64 AppImage](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.5/clash-verge_1.4.5_amd64.AppImage) - [Linux x64 AppImage](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.6/clash-verge_1.4.6_amd64.AppImage)
- [Linux x64 deb](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.5/clash-verge_1.4.5_amd64.deb) - [Linux x64 deb](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.6/clash-verge_1.4.6_amd64.deb)
- [Linux x86 AppImage](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.5/clash-verge_1.4.5_i386.AppImage) - [Linux x86 AppImage](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.6/clash-verge_1.4.6_i386.AppImage)
- [Linux x86 deb](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.5/clash-verge_1.4.5_i386.deb) - [Linux x86 deb](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.6/clash-verge_1.4.6_i386.deb)
- [Linux arm64 deb](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.5/clash-verge_1.4.5_arm64.deb) - [Linux arm64 deb](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.6/clash-verge_1.4.6_arm64.deb)
Or you can build it yourself. Supports Windows, Linux and macOS 10.15+ Or you can build it yourself. Supports Windows, Linux and macOS 10.15+

View File

@ -1,3 +1,12 @@
## v1.4.6
### Features
- 更新 Clash Meta(mihomo) Core to v1.18.0
- UI 优化调整
---
## v1.4.5 ## v1.4.5
### Features ### Features

View File

@ -1,6 +1,6 @@
{ {
"name": "clash-verge", "name": "clash-verge",
"version": "1.4.5", "version": "1.4.6",
"license": "GPL-3.0", "license": "GPL-3.0",
"scripts": { "scripts": {
"dev": "tauri dev", "dev": "tauri dev",

2
src-tauri/Cargo.lock generated
View File

@ -559,7 +559,7 @@ dependencies = [
[[package]] [[package]]
name = "clash-verge" name = "clash-verge"
version = "1.4.5" version = "1.4.6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"auto-launch", "auto-launch",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "clash-verge" name = "clash-verge"
version = "1.4.5" version = "1.4.6"
description = "clash verge" description = "clash verge"
authors = ["zzzgydi", "wonfen", "MystiPanda"] authors = ["zzzgydi", "wonfen", "MystiPanda"]
license = "GPL-3.0" license = "GPL-3.0"

View File

@ -1,7 +1,7 @@
{ {
"package": { "package": {
"productName": "Clash Verge", "productName": "Clash Verge",
"version": "1.4.5" "version": "1.4.6"
}, },
"build": { "build": {
"distDir": "../dist", "distDir": "../dist",

View File

@ -27,15 +27,25 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
overflow: auto; overflow: auto;
padding: 5px 5px; padding: 10px 0;
box-sizing: border-box; box-sizing: border-box;
scrollbar-gutter: stable; scrollbar-gutter: stable;
.base-content { .base-content {
width: 100%; width: calc(100% - 10px * 2);
// max-width: 850px;
margin: 0 auto; margin: 0 auto;
} }
} }
&.no-padding {
> section {
padding: 0;
overflow: visible;
.base-content {
width: 100%;
}
}
}
} }
} }

View File

@ -8,10 +8,11 @@ interface Props {
header?: React.ReactNode; // something behind title header?: React.ReactNode; // something behind title
contentStyle?: React.CSSProperties; contentStyle?: React.CSSProperties;
children?: ReactNode; children?: ReactNode;
full?: boolean;
} }
export const BasePage: React.FC<Props> = (props) => { export const BasePage: React.FC<Props> = (props) => {
const { title, header, contentStyle, children } = props; const { title, header, contentStyle, full, children } = props;
const { theme } = useCustomTheme(); const { theme } = useCustomTheme();
const isDark = theme.palette.mode === "dark"; const isDark = theme.palette.mode === "dark";
@ -28,7 +29,7 @@ export const BasePage: React.FC<Props> = (props) => {
</header> </header>
<div <div
className="base-container" className={full ? "base-container no-padding" : "base-container"}
style={{ backgroundColor: isDark ? "#090909" : "#ffffff" }} style={{ backgroundColor: isDark ? "#090909" : "#ffffff" }}
> >
<section <section

View File

@ -114,6 +114,7 @@ const ConnectionsPage = () => {
return ( return (
<BasePage <BasePage
full
title={t("Connections")} title={t("Connections")}
contentStyle={{ height: "100%" }} contentStyle={{ height: "100%" }}
header={ header={
@ -142,75 +143,72 @@ const ConnectionsPage = () => {
</Box> </Box>
} }
> >
<Box sx={{ boxShadow: 0, height: "100%" }}> <Box
<Box sx={{
sx={{ pt: 1,
pt: 1, mb: 0.5,
mb: 0.5, mx: "10px",
mx: "12px", height: "36px",
height: "36px", display: "flex",
display: "flex", alignItems: "center",
alignItems: "center", userSelect: "text",
userSelect: "text", }}
}} >
> {!isTableLayout && (
{!isTableLayout && ( <Select
<Select
size="small"
autoComplete="off"
value={curOrderOpt}
onChange={(e) => setOrderOpt(e.target.value)}
sx={{
mr: 1,
width: i18n.language === "en" ? 190 : 120,
'[role="button"]': { py: 0.65 },
}}
>
{Object.keys(orderOpts).map((opt) => (
<MenuItem key={opt} value={opt}>
<span style={{ fontSize: 14 }}>{t(opt)}</span>
</MenuItem>
))}
</Select>
)}
<TextField
hiddenLabel
fullWidth
size="small" size="small"
autoComplete="off" autoComplete="off"
spellCheck="false" value={curOrderOpt}
variant="outlined" onChange={(e) => setOrderOpt(e.target.value)}
placeholder={t("Filter conditions")} sx={{
value={filterText} mr: 1,
onChange={(e) => setFilterText(e.target.value)} width: i18n.language === "en" ? 190 : 120,
sx={{ input: { py: 0.65, px: 1.25 } }} '[role="button"]': { py: 0.65 },
/> }}
</Box> >
{Object.keys(orderOpts).map((opt) => (
<MenuItem key={opt} value={opt}>
<span style={{ fontSize: 14 }}>{t(opt)}</span>
</MenuItem>
))}
</Select>
)}
<Box height="calc(100% - 50px)" sx={{ userSelect: "text" }}> <TextField
{filterConn.length === 0 ? ( hiddenLabel
<BaseEmpty text="No Connections" /> fullWidth
) : isTableLayout ? ( size="small"
<ConnectionTable autoComplete="off"
connections={filterConn} spellCheck="false"
onShowDetail={(detail) => detailRef.current?.open(detail)} variant="outlined"
/> placeholder={t("Filter conditions")}
) : ( value={filterText}
<Virtuoso onChange={(e) => setFilterText(e.target.value)}
data={filterConn} sx={{ input: { py: 0.65, px: 1.25 } }}
itemContent={(index, item) => ( />
<ConnectionItem
value={item}
onShowDetail={() => detailRef.current?.open(item)}
/>
)}
/>
)}
</Box>
<ConnectionDetail ref={detailRef} />
</Box> </Box>
<Box height="calc(100% - 50px)" sx={{ userSelect: "text" }}>
{filterConn.length === 0 ? (
<BaseEmpty text="No Connections" />
) : isTableLayout ? (
<ConnectionTable
connections={filterConn}
onShowDetail={(detail) => detailRef.current?.open(detail)}
/>
) : (
<Virtuoso
data={filterConn}
itemContent={(index, item) => (
<ConnectionItem
value={item}
onShowDetail={() => detailRef.current?.open(item)}
/>
)}
/>
)}
</Box>
<ConnectionDetail ref={detailRef} />
</BasePage> </BasePage>
); );
}; };

View File

@ -38,6 +38,7 @@ const LogPage = () => {
return ( return (
<BasePage <BasePage
full
title={t("Logs")} title={t("Logs")}
contentStyle={{ height: "100%" }} contentStyle={{ height: "100%" }}
header={ header={
@ -66,61 +67,52 @@ const LogPage = () => {
> >
<Box <Box
sx={{ sx={{
boxSizing: "border-box", pt: 1,
boxShadow: 0, mb: 0.5,
height: "100%", mx: "10px",
userSelect: "text", height: "36px",
display: "flex",
alignItems: "center",
}} }}
> >
<Box <Select
sx={{ size="small"
pt: 1, autoComplete="off"
mb: 0.5, value={logState}
mx: "12px", onChange={(e) => setLogState(e.target.value)}
height: "36px", sx={{ width: 120, mr: 1, '[role="button"]': { py: 0.65 } }}
display: "flex",
alignItems: "center",
}}
> >
<Select <MenuItem value="all">ALL</MenuItem>
size="small" <MenuItem value="inf">INFO</MenuItem>
autoComplete="off" <MenuItem value="warn">WARN</MenuItem>
value={logState} <MenuItem value="err">ERROR</MenuItem>
onChange={(e) => setLogState(e.target.value)} </Select>
sx={{ width: 120, mr: 1, '[role="button"]': { py: 0.65 } }}
>
<MenuItem value="all">ALL</MenuItem>
<MenuItem value="inf">INFO</MenuItem>
<MenuItem value="warn">WARN</MenuItem>
<MenuItem value="err">ERROR</MenuItem>
</Select>
<TextField <TextField
hiddenLabel hiddenLabel
fullWidth fullWidth
size="small" size="small"
autoComplete="off" autoComplete="off"
spellCheck="false" spellCheck="false"
variant="outlined" variant="outlined"
placeholder={t("Filter conditions")} placeholder={t("Filter conditions")}
value={filterText} value={filterText}
onChange={(e) => setFilterText(e.target.value)} onChange={(e) => setFilterText(e.target.value)}
sx={{ input: { py: 0.65, px: 1.25 } }} sx={{ input: { py: 0.65, px: 1.25 } }}
/>
</Box>
<Box height="calc(100% - 50px)">
{filterLogs.length > 0 ? (
<Virtuoso
initialTopMostItemIndex={999}
data={filterLogs}
itemContent={(index, item) => <LogItem value={item} />}
followOutput={"smooth"}
/> />
</Box> ) : (
<BaseEmpty text="No Logs" />
<Box height="calc(100% - 50px)"> )}
{filterLogs.length > 0 ? (
<Virtuoso
initialTopMostItemIndex={999}
data={filterLogs}
itemContent={(index, item) => <LogItem value={item} />}
followOutput={"smooth"}
/>
) : (
<BaseEmpty text="No Logs" />
)}
</Box>
</Box> </Box>
</BasePage> </BasePage>
); );

View File

@ -51,6 +51,7 @@ const ProxyPage = () => {
return ( return (
<BasePage <BasePage
full
contentStyle={{ height: "100%" }} contentStyle={{ height: "100%" }}
title={t("Proxy Groups")} title={t("Proxy Groups")}
header={ header={
@ -72,16 +73,7 @@ const ProxyPage = () => {
</Box> </Box>
} }
> >
<Box <ProxyGroups mode={curMode!} />
sx={{
borderRadius: 1,
boxShadow: 0,
height: "100%",
boxSizing: "border-box",
}}
>
<ProxyGroups mode={curMode!} />
</Box>
</BasePage> </BasePage>
); );
}; };

View File

@ -18,45 +18,43 @@ const RulesPage = () => {
}, [data, filterText]); }, [data, filterText]);
return ( return (
<BasePage title={t("Rules")} contentStyle={{ height: "100%" }}> <BasePage full title={t("Rules")} contentStyle={{ height: "100%" }}>
<Box sx={{ boxSizing: "border-box", boxShadow: 0, height: "100%" }}> <Box
<Box sx={{
sx={{ pt: 1,
pt: 1, mb: 0.5,
mb: 0.5, mx: "10px",
mx: "12px", height: "36px",
height: "36px", display: "flex",
display: "flex", alignItems: "center",
alignItems: "center", }}
}} >
> <TextField
<TextField hiddenLabel
hiddenLabel fullWidth
fullWidth size="small"
size="small" autoComplete="off"
autoComplete="off" variant="outlined"
variant="outlined" spellCheck="false"
spellCheck="false" placeholder={t("Filter conditions")}
placeholder={t("Filter conditions")} value={filterText}
value={filterText} onChange={(e) => setFilterText(e.target.value)}
onChange={(e) => setFilterText(e.target.value)} sx={{ input: { py: 0.65, px: 1.25 } }}
sx={{ input: { py: 0.65, px: 1.25 } }} />
/> </Box>
</Box>
<Box height="calc(100% - 50px)"> <Box height="calc(100% - 50px)">
{rules.length > 0 ? ( {rules.length > 0 ? (
<Virtuoso <Virtuoso
data={rules} data={rules}
itemContent={(index, item) => ( itemContent={(index, item) => (
<RuleItem index={index + 1} value={item} /> <RuleItem index={index + 1} value={item} />
)} )}
followOutput={"smooth"} followOutput={"smooth"}
/> />
) : ( ) : (
<BaseEmpty text="No Rules" /> <BaseEmpty text="No Rules" />
)} )}
</Box>
</Box> </Box>
</BasePage> </BasePage>
); );