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).
- [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 x86](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.5/Clash.Verge_1.4.5_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 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.6/Clash.Verge_1.4.6_x86-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 apple](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.5/Clash.Verge_1.4.5_aarch64.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.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 deb](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.5/clash-verge_1.4.5_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 deb](https://github.com/clash-verge-rev/clash-verge-rev/releases/download/v1.4.5/clash-verge_1.4.5_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 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.6/clash-verge_1.4.6_amd64.deb)
- [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.6/clash-verge_1.4.6_i386.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+

View File

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

View File

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

2
src-tauri/Cargo.lock generated
View File

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

View File

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

View File

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

View File

@ -27,15 +27,25 @@
width: 100%;
height: 100%;
overflow: auto;
padding: 5px 5px;
padding: 10px 0;
box-sizing: border-box;
scrollbar-gutter: stable;
.base-content {
width: 100%;
// max-width: 850px;
width: calc(100% - 10px * 2);
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
contentStyle?: React.CSSProperties;
children?: ReactNode;
full?: boolean;
}
export const BasePage: React.FC<Props> = (props) => {
const { title, header, contentStyle, children } = props;
const { title, header, contentStyle, full, children } = props;
const { theme } = useCustomTheme();
const isDark = theme.palette.mode === "dark";
@ -28,7 +29,7 @@ export const BasePage: React.FC<Props> = (props) => {
</header>
<div
className="base-container"
className={full ? "base-container no-padding" : "base-container"}
style={{ backgroundColor: isDark ? "#090909" : "#ffffff" }}
>
<section

View File

@ -114,6 +114,7 @@ const ConnectionsPage = () => {
return (
<BasePage
full
title={t("Connections")}
contentStyle={{ height: "100%" }}
header={
@ -142,75 +143,72 @@ const ConnectionsPage = () => {
</Box>
}
>
<Box sx={{ boxShadow: 0, height: "100%" }}>
<Box
sx={{
pt: 1,
mb: 0.5,
mx: "12px",
height: "36px",
display: "flex",
alignItems: "center",
userSelect: "text",
}}
>
{!isTableLayout && (
<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
<Box
sx={{
pt: 1,
mb: 0.5,
mx: "10px",
height: "36px",
display: "flex",
alignItems: "center",
userSelect: "text",
}}
>
{!isTableLayout && (
<Select
size="small"
autoComplete="off"
spellCheck="false"
variant="outlined"
placeholder={t("Filter conditions")}
value={filterText}
onChange={(e) => setFilterText(e.target.value)}
sx={{ input: { py: 0.65, px: 1.25 } }}
/>
</Box>
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>
)}
<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} />
<TextField
hiddenLabel
fullWidth
size="small"
autoComplete="off"
spellCheck="false"
variant="outlined"
placeholder={t("Filter conditions")}
value={filterText}
onChange={(e) => setFilterText(e.target.value)}
sx={{ input: { py: 0.65, px: 1.25 } }}
/>
</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>
);
};

View File

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

View File

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

View File

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