fix: standardize RunningMode handling between frontend and backend

This commit improves the type consistency between the Rust backend and TypeScript frontend by:

1. Modifying the Rust `get_running_mode()` command to return a String instead of RunningMode enum directly
2. Removing the RunningMode enum and IRunningMode interface from TypeScript types
3. Using string literals for mode comparison in frontend components
4. Standardizing on capitalized mode names (e.g., "Sidecar" instead of "sidecar")

These changes ensure proper serialization/deserialization between backend and frontend,
making the code more maintainable and reducing potential inconsistencies.
This commit is contained in:
Tunglies
2025-03-26 22:04:16 +08:00
parent 6e40dd9862
commit 7ede91599c
7 changed files with 134 additions and 145 deletions

View File

@@ -32,71 +32,64 @@ interface TabButtonProps {
}
// 抽取Tab组件以减少重复代码
const TabButton: FC<TabButtonProps> = memo(({
isActive,
onClick,
icon: Icon,
label,
hasIndicator = false
}) => (
<Paper
elevation={isActive ? 2 : 0}
onClick={onClick}
sx={{
cursor: "pointer",
px: 2,
py: 1,
display: "flex",
alignItems: "center",
justifyContent: "center",
gap: 1,
bgcolor: isActive ? "primary.main" : "background.paper",
color: isActive ? "primary.contrastText" : "text.primary",
borderRadius: 1.5,
flex: 1,
maxWidth: 160,
transition: "all 0.2s ease-in-out",
position: "relative",
"&:hover": {
transform: "translateY(-1px)",
boxShadow: 1,
},
"&:after": isActive
? {
content: '""',
position: "absolute",
bottom: -9,
left: "50%",
width: 2,
height: 9,
bgcolor: "primary.main",
transform: "translateX(-50%)",
}
: {},
}}
>
<Icon fontSize="small" />
<Typography
variant="body2"
sx={{ fontWeight: isActive ? 600 : 400 }}
const TabButton: FC<TabButtonProps> = memo(
({ isActive, onClick, icon: Icon, label, hasIndicator = false }) => (
<Paper
elevation={isActive ? 2 : 0}
onClick={onClick}
sx={{
cursor: "pointer",
px: 2,
py: 1,
display: "flex",
alignItems: "center",
justifyContent: "center",
gap: 1,
bgcolor: isActive ? "primary.main" : "background.paper",
color: isActive ? "primary.contrastText" : "text.primary",
borderRadius: 1.5,
flex: 1,
maxWidth: 160,
transition: "all 0.2s ease-in-out",
position: "relative",
"&:hover": {
transform: "translateY(-1px)",
boxShadow: 1,
},
"&:after": isActive
? {
content: '""',
position: "absolute",
bottom: -9,
left: "50%",
width: 2,
height: 9,
bgcolor: "primary.main",
transform: "translateX(-50%)",
}
: {},
}}
>
{label}
</Typography>
{hasIndicator && (
<Box
sx={{
width: 8,
height: 8,
borderRadius: "50%",
bgcolor: isActive ? "#fff" : "success.main",
position: "absolute",
top: 8,
right: 8,
}}
/>
)}
</Paper>
));
<Icon fontSize="small" />
<Typography variant="body2" sx={{ fontWeight: isActive ? 600 : 400 }}>
{label}
</Typography>
{hasIndicator && (
<Box
sx={{
width: 8,
height: 8,
borderRadius: "50%",
bgcolor: isActive ? "#fff" : "success.main",
position: "absolute",
top: 8,
right: 8,
}}
/>
)}
</Paper>
),
);
interface TabDescriptionProps {
description: string;
@@ -104,44 +97,46 @@ interface TabDescriptionProps {
}
// 抽取描述文本组件
const TabDescription: FC<TabDescriptionProps> = memo(({ description, tooltipTitle }) => (
<Fade in={true} timeout={200}>
<Typography
variant="caption"
component="div"
sx={{
width: "95%",
textAlign: "center",
color: "text.secondary",
p: 0.8,
borderRadius: 1,
borderColor: "primary.main",
borderWidth: 1,
borderStyle: "solid",
backgroundColor: "background.paper",
display: "flex",
alignItems: "center",
justifyContent: "center",
gap: 0.5,
wordBreak: "break-word",
hyphens: "auto",
}}
>
{description}
<Tooltip title={tooltipTitle}>
<HelpOutlineRounded
sx={{ fontSize: 14, opacity: 0.7, flexShrink: 0 }}
/>
</Tooltip>
</Typography>
</Fade>
));
const TabDescription: FC<TabDescriptionProps> = memo(
({ description, tooltipTitle }) => (
<Fade in={true} timeout={200}>
<Typography
variant="caption"
component="div"
sx={{
width: "95%",
textAlign: "center",
color: "text.secondary",
p: 0.8,
borderRadius: 1,
borderColor: "primary.main",
borderWidth: 1,
borderStyle: "solid",
backgroundColor: "background.paper",
display: "flex",
alignItems: "center",
justifyContent: "center",
gap: 0.5,
wordBreak: "break-word",
hyphens: "auto",
}}
>
{description}
<Tooltip title={tooltipTitle}>
<HelpOutlineRounded
sx={{ fontSize: 14, opacity: 0.7, flexShrink: 0 }}
/>
</Tooltip>
</Typography>
</Fade>
),
);
export const ProxyTunCard: FC = () => {
const { t } = useTranslation();
const theme = useTheme();
const [activeTab, setActiveTab] = useState<string>(() =>
localStorage.getItem(LOCAL_STORAGE_TAB_KEY) || "system"
const [activeTab, setActiveTab] = useState<string>(
() => localStorage.getItem(LOCAL_STORAGE_TAB_KEY) || "system",
);
// 获取代理状态信息
@@ -152,7 +147,7 @@ export const ProxyTunCard: FC = () => {
const { enable_system_proxy, enable_tun_mode } = verge ?? {};
// 是否以sidecar模式运行
const isSidecarMode = runningMode === "sidecar";
const isSidecarMode = runningMode === "Sidecar";
// 处理错误
const handleError = (err: Error) => {
@@ -172,7 +167,7 @@ export const ProxyTunCard: FC = () => {
text: enable_system_proxy
? t("System Proxy Enabled")
: t("System Proxy Disabled"),
tooltip: t("System Proxy Info")
tooltip: t("System Proxy Info"),
};
} else {
return {
@@ -181,7 +176,7 @@ export const ProxyTunCard: FC = () => {
: enable_tun_mode
? t("TUN Mode Enabled")
: t("TUN Mode Disabled"),
tooltip: t("TUN Mode Intercept Info")
tooltip: t("TUN Mode Intercept Info"),
};
}
}, [activeTab, enable_system_proxy, enable_tun_mode, isSidecarMode, t]);