diff --git a/src/assets/image/map.svg b/src/assets/image/map.svg new file mode 100644 index 00000000..8711b111 --- /dev/null +++ b/src/assets/image/map.svg @@ -0,0 +1,422 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/home/power-button.tsx b/src/components/home/power-button.tsx new file mode 100644 index 00000000..d1d94cab --- /dev/null +++ b/src/components/home/power-button.tsx @@ -0,0 +1,56 @@ +import React from 'react'; +import { cn } from '@root/lib/utils'; +import { Power } from 'lucide-react'; + +export interface PowerButtonProps extends React.ButtonHTMLAttributes { + checked?: boolean; + loading?: boolean; +} + +export const PowerButton = React.forwardRef( + ({ className, checked = false, loading = false, ...props }, ref) => { + const state = checked ? 'on' : 'off'; + + return ( + + + + + + + + + {loading && ( + + + + )} + + ); + } +); \ No newline at end of file diff --git a/src/index.css b/src/index.css index 875c37e9..1ca96867 100644 --- a/src/index.css +++ b/src/index.css @@ -131,3 +131,21 @@ svg { stroke-width: var(--icon-stroke-width, 2); } + + +@keyframes gradient-wave { + 0% { + background-position: -200% center; + } + 100% { + background-position: 200% center; + } +} + +.animate-gradient-wave { + background-size: 200% auto; + background-clip: text; + -webkit-background-clip: text; + color: transparent; + animation: gradient-wave 2s linear infinite; +} diff --git a/src/pages/home.tsx b/src/pages/home.tsx index cf7944c2..b81d6aff 100644 --- a/src/pages/home.tsx +++ b/src/pages/home.tsx @@ -39,6 +39,8 @@ import { updateProfile } from "@/services/cmds"; import { SidebarTrigger } from "@/components/ui/sidebar"; import parseTraffic from "@/utils/parse-traffic"; import { useAppData } from "@/providers/app-data-provider"; +import {PowerButton} from "@/components/home/power-button"; +import {cn} from "@root/lib/utils"; const MinimalHomePage: React.FC = () => { const { t } = useTranslation(); @@ -154,8 +156,48 @@ const MinimalHomePage: React.FC = () => { } }); + const statusInfo = useMemo(() => { + if (isToggling) { + return { + text: isProxyEnabled ? t('Disconnecting...') : t('Connecting...'), + color: isProxyEnabled ? '#f59e0b' : '#84cc16', + isAnimating: true, + }; + } + if (isProxyEnabled) { + return { + text: t('Connected'), + color: '#22c55e', + isAnimating: false, + }; + } + return { + text: t('Disconnected'), + color: '#ef4444', + isAnimating: false, + }; + }, [isToggling, isProxyEnabled, t]); + return ( + + + + + {isProxyEnabled && ( + + )} + @@ -242,15 +284,18 @@ const MinimalHomePage: React.FC = () => { )} )} - - - {isProxyEnabled ? t("Connected") : t("Disconnected")} - + + + {statusInfo.text} + {isProxyEnabled && ( - + {parseTraffic(connections.downloadTotal)} @@ -261,23 +306,18 @@ const MinimalHomePage: React.FC = () => { )} - - - {isToggling && - (isProxyEnabled ? t("Disconnecting...") : t("Connecting..."))} - - - + - {showTunAlert && (
- {isToggling && - (isProxyEnabled ? t("Disconnecting...") : t("Connecting..."))} -