feat: add proxy auto scroll toggle setting (#3674)

* feat: add proxy auto scroll toggle setting

* refactor: rename enable_proxy_auto_scroll to enable_hover_jump_navigator

* 参考 Unified Delay 调整式样
This commit is contained in:
rebecca554owen
2025-06-11 13:21:24 +08:00
committed by GitHub
parent 22eac1a832
commit 4f474e1098
7 changed files with 52 additions and 5 deletions

View File

@@ -200,6 +200,9 @@ pub struct IVerge {
/// 自动进入轻量模式的延迟(分钟) /// 自动进入轻量模式的延迟(分钟)
pub auto_light_weight_minutes: Option<u64>, pub auto_light_weight_minutes: Option<u64>,
/// 启用代理页面自动滚动
pub enable_hover_jump_navigator: Option<bool>,
/// 服务状态跟踪 /// 服务状态跟踪
pub service_state: Option<crate::core::service::ServiceState>, pub service_state: Option<crate::core::service::ServiceState>,
} }
@@ -275,6 +278,7 @@ impl IVerge {
tun_tray_icon: Some(false), tun_tray_icon: Some(false),
enable_auto_launch: Some(false), enable_auto_launch: Some(false),
enable_silent_start: Some(false), enable_silent_start: Some(false),
enable_hover_jump_navigator: Some(true),
enable_system_proxy: Some(false), enable_system_proxy: Some(false),
proxy_auto_config: Some(false), proxy_auto_config: Some(false),
pac_file_content: Some(DEFAULT_PAC.into()), pac_file_content: Some(DEFAULT_PAC.into()),
@@ -351,6 +355,7 @@ impl IVerge {
patch!(enable_tun_mode); patch!(enable_tun_mode);
patch!(enable_auto_launch); patch!(enable_auto_launch);
patch!(enable_silent_start); patch!(enable_silent_start);
patch!(enable_hover_jump_navigator);
patch!(enable_random_port); patch!(enable_random_port);
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
patch!(verge_redir_port); patch!(verge_redir_port);
@@ -492,6 +497,7 @@ pub struct IVergeResponse {
pub auto_light_weight_minutes: Option<u64>, pub auto_light_weight_minutes: Option<u64>,
pub enable_dns_settings: Option<bool>, pub enable_dns_settings: Option<bool>,
pub home_cards: Option<serde_json::Value>, pub home_cards: Option<serde_json::Value>,
pub enable_hover_jump_navigator: Option<bool>,
pub service_state: Option<crate::core::service::ServiceState>, pub service_state: Option<crate::core::service::ServiceState>,
} }
@@ -561,6 +567,7 @@ impl From<IVerge> for IVergeResponse {
auto_light_weight_minutes: verge.auto_light_weight_minutes, auto_light_weight_minutes: verge.auto_light_weight_minutes,
enable_dns_settings: verge.enable_dns_settings, enable_dns_settings: verge.enable_dns_settings,
home_cards: verge.home_cards, home_cards: verge.home_cards,
enable_hover_jump_navigator: verge.enable_hover_jump_navigator,
service_state: verge.service_state, service_state: verge.service_state,
} }
} }

View File

@@ -106,10 +106,12 @@ const LetterItem = memo(
name, name,
onClick, onClick,
getFirstChar, getFirstChar,
enableAutoScroll = true,
}: { }: {
name: string; name: string;
onClick: (name: string) => void; onClick: (name: string) => void;
getFirstChar: (str: string) => string; getFirstChar: (str: string) => string;
enableAutoScroll?: boolean;
}) => { }) => {
const [showTooltip, setShowTooltip] = useState(false); const [showTooltip, setShowTooltip] = useState(false);
const letterRef = useRef<HTMLDivElement>(null); const letterRef = useRef<HTMLDivElement>(null);
@@ -136,11 +138,14 @@ const LetterItem = memo(
const handleMouseEnter = useCallback(() => { const handleMouseEnter = useCallback(() => {
setShowTooltip(true); setShowTooltip(true);
// 添加 200ms 的延迟,避免鼠标快速划过时触发滚动 // 只有在启用自动滚动时才触发滚动
if (enableAutoScroll) {
// 添加 100ms 的延迟,避免鼠标快速划过时触发滚动
hoverTimeoutRef.current = setTimeout(() => { hoverTimeoutRef.current = setTimeout(() => {
onClick(name); onClick(name);
}, 100); }, 100);
}, [name, onClick]); }
}, [name, onClick, enableAutoScroll]);
const handleMouseLeave = useCallback(() => { const handleMouseLeave = useCallback(() => {
setShowTooltip(false); setShowTooltip(false);
@@ -198,6 +203,9 @@ export const ProxyGroups = (props: Props) => {
const { verge } = useVerge(); const { verge } = useVerge();
const { current, patchCurrent } = useProfiles(); const { current, patchCurrent } = useProfiles();
// 获取自动滚动开关状态,默认为 true
const enableAutoScroll = verge?.enable_hover_jump_navigator ?? true;
const timeout = verge?.default_latency_timeout || 10000; const timeout = verge?.default_latency_timeout || 10000;
const virtuosoRef = useRef<VirtuosoHandle>(null); const virtuosoRef = useRef<VirtuosoHandle>(null);
@@ -541,6 +549,7 @@ export const ProxyGroups = (props: Props) => {
name={name} name={name}
onClick={handleLetterClick} onClick={handleLetterClick}
getFirstChar={getFirstChar} getFirstChar={getFirstChar}
enableAutoScroll={enableAutoScroll}
/> />
))} ))}
</div> </div>

View File

@@ -12,6 +12,7 @@ import {
} from "@mui/material"; } from "@mui/material";
import { useVerge } from "@/hooks/use-verge"; import { useVerge } from "@/hooks/use-verge";
import { BaseDialog, DialogRef, Switch } from "@/components/base"; import { BaseDialog, DialogRef, Switch } from "@/components/base";
import { TooltipIcon } from "@/components/base/base-tooltip-icon";
import { GuardState } from "./guard-state"; import { GuardState } from "./guard-state";
import { open as openDialog } from "@tauri-apps/plugin-dialog"; import { open as openDialog } from "@tauri-apps/plugin-dialog";
import { convertFileSrc } from "@tauri-apps/api/core"; import { convertFileSrc } from "@tauri-apps/api/core";
@@ -147,6 +148,30 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
</GuardState> </GuardState>
</Item> </Item>
<Item>
<ListItemText
primary={
<Box sx={{ display: "flex", alignItems: "center", gap: 0.5 }}>
<span>{t("Hover Jump Navigator")}</span>
<TooltipIcon
title={t("Hover Jump Navigator Info")}
sx={{ opacity: "0.7" }}
/>
</Box>
}
/>
<GuardState
value={verge?.enable_hover_jump_navigator ?? true}
valueProps="checked"
onCatch={onError}
onFormat={onSwitchFormat}
onChange={(e) => onChangeData({ enable_hover_jump_navigator: e })}
onGuard={(e) => patchVerge({ enable_hover_jump_navigator: e })}
>
<Switch edge="end" />
</GuardState>
</Item>
<Item> <Item>
<ListItemText primary={t("Nav Icon")} /> <ListItemText primary={t("Nav Icon")} />
<GuardState <GuardState

View File

@@ -58,6 +58,7 @@ const SettingSystem = ({ onError }: Props) => {
enable_silent_start, enable_silent_start,
enable_system_proxy, enable_system_proxy,
proxy_auto_config, proxy_auto_config,
enable_hover_jump_navigator,
} = verge ?? {}; } = verge ?? {};
const onSwitchFormat = (_e: any, value: boolean) => value; const onSwitchFormat = (_e: any, value: boolean) => value;

View File

@@ -261,6 +261,8 @@
"Administrator mode may not support auto launch": "Administrator mode may not support auto launch", "Administrator mode may not support auto launch": "Administrator mode may not support auto launch",
"Silent Start": "Silent Start", "Silent Start": "Silent Start",
"Silent Start Info": "Start the program in background mode without displaying the panel", "Silent Start Info": "Start the program in background mode without displaying the panel",
"Hover Jump Navigator": "Hover Jump Navigator",
"Hover Jump Navigator Info": "Automatically scroll to the corresponding proxy group when hovering over alphabet letters",
"TG Channel": "Telegram Channel", "TG Channel": "Telegram Channel",
"Manual": "Manual", "Manual": "Manual",
"Github Repo": "Github Repo", "Github Repo": "Github Repo",

View File

@@ -261,6 +261,8 @@
"Administrator mode may not support auto launch": "管理员模式可能不支持开机自启", "Administrator mode may not support auto launch": "管理员模式可能不支持开机自启",
"Silent Start": "静默启动", "Silent Start": "静默启动",
"Silent Start Info": "程序启动时以后台模式运行,不显示程序面板", "Silent Start Info": "程序启动时以后台模式运行,不显示程序面板",
"Hover Jump Navigator": "悬浮跳转导航",
"Hover Jump Navigator Info": "鼠标悬停在字母上时自动滚动到对应代理组",
"TG Channel": "Telegram 频道", "TG Channel": "Telegram 频道",
"Manual": "使用手册", "Manual": "使用手册",
"Github Repo": "GitHub 项目地址", "Github Repo": "GitHub 项目地址",

View File

@@ -792,6 +792,7 @@ interface IVergeConfig {
webdav_username?: string; webdav_username?: string;
webdav_password?: string; webdav_password?: string;
home_cards?: Record<string, boolean>; home_cards?: Record<string, boolean>;
enable_hover_jump_navigator?: boolean;
} }
interface IWebDavFile { interface IWebDavFile {