mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-02 18:39:06 +08:00
refactor(hooks): improve scroll position hook with timer utility
- Replace setTimeout with useTimer utility for better cleanup - Add throttleWait parameter for configurable scroll throttling - Update documentation to reflect changes
This commit is contained in:
parent
6d8edc95d9
commit
0a80fc5517
@ -1,30 +1,32 @@
|
||||
import { throttle } from 'lodash'
|
||||
import { useEffect, useRef } from 'react'
|
||||
|
||||
export default function useScrollPosition(key: string) {
|
||||
import { useTimer } from './useTimer'
|
||||
|
||||
/**
|
||||
* A custom hook that manages scroll position persistence for a container element
|
||||
* @param key - A unique identifier used to store/retrieve the scroll position
|
||||
* @returns An object containing:
|
||||
* - containerRef: React ref for the scrollable container
|
||||
* - handleScroll: Throttled scroll event handler that saves scroll position
|
||||
*/
|
||||
export default function useScrollPosition(key: string, throttleWait?: number) {
|
||||
const containerRef = useRef<HTMLDivElement>(null)
|
||||
const scrollKey = `scroll:${key}`
|
||||
const scrollTimerRef = useRef<NodeJS.Timeout>(undefined)
|
||||
const { setTimeoutTimer } = useTimer()
|
||||
|
||||
const handleScroll = throttle(() => {
|
||||
const position = containerRef.current?.scrollTop ?? 0
|
||||
window.requestAnimationFrame(() => {
|
||||
window.keyv.set(scrollKey, position)
|
||||
})
|
||||
}, 100)
|
||||
}, throttleWait ?? 100)
|
||||
|
||||
useEffect(() => {
|
||||
const scroll = () => containerRef.current?.scrollTo({ top: window.keyv.get(scrollKey) || 0 })
|
||||
scroll()
|
||||
clearTimeout(scrollTimerRef.current)
|
||||
scrollTimerRef.current = setTimeout(scroll, 50)
|
||||
}, [scrollKey])
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
clearTimeout(scrollTimerRef.current)
|
||||
}
|
||||
}, [])
|
||||
setTimeoutTimer('scrollEffect', scroll, 50)
|
||||
}, [scrollKey, setTimeoutTimer])
|
||||
|
||||
return { containerRef, handleScroll }
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { Alert, Card, CardBody, CardHeader, Chip, Input, Switch } from '@heroui/react'
|
||||
import { useAgentClient } from '@renderer/hooks/agents/useAgentClient'
|
||||
import { useMCPServers } from '@renderer/hooks/useMCPServers'
|
||||
import useScrollPosition from '@renderer/hooks/useScrollPosition'
|
||||
import {
|
||||
AgentConfiguration,
|
||||
AgentConfigurationSchema,
|
||||
@ -11,7 +12,7 @@ import {
|
||||
} from '@renderer/types'
|
||||
import { Modal } from 'antd'
|
||||
import { ShieldAlert, ShieldCheck, Wrench } from 'lucide-react'
|
||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { FC, startTransition, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { mutate } from 'swr'
|
||||
|
||||
@ -105,6 +106,7 @@ const computeModeDefaults = (mode: PermissionMode, tools: Tool[]): string[] => {
|
||||
const unique = (values: string[]) => Array.from(new Set(values))
|
||||
|
||||
export const AgentToolingSettings: FC<AgentToolingSettingsProps> = ({ agent, updateAgent }) => {
|
||||
const { containerRef, handleScroll } = useScrollPosition('AgentToolingSettings', 100)
|
||||
const { t } = useTranslation()
|
||||
const client = useAgentClient()
|
||||
const { mcpServers: allServers } = useMCPServers()
|
||||
@ -252,22 +254,26 @@ export const AgentToolingSettings: FC<AgentToolingSettingsProps> = ({ agent, upd
|
||||
if (!agent || isUpdatingTools) {
|
||||
return
|
||||
}
|
||||
setApprovedToolIds((prev) => {
|
||||
const exists = prev.includes(toolId)
|
||||
if (isApproved === exists) {
|
||||
return prev
|
||||
}
|
||||
const next = isApproved ? [...prev, toolId] : prev.filter((id) => id !== toolId)
|
||||
const sanitized = unique(next.filter((id) => availableTools.some((tool) => tool.id === id)).concat(autoToolIds))
|
||||
setIsUpdatingTools(true)
|
||||
void (async () => {
|
||||
try {
|
||||
await updateAgent({ id: agent.id, allowed_tools: sanitized })
|
||||
} finally {
|
||||
setIsUpdatingTools(false)
|
||||
startTransition(() => {
|
||||
setApprovedToolIds((prev) => {
|
||||
const exists = prev.includes(toolId)
|
||||
if (isApproved === exists) {
|
||||
return prev
|
||||
}
|
||||
})()
|
||||
return sanitized
|
||||
const next = isApproved ? [...prev, toolId] : prev.filter((id) => id !== toolId)
|
||||
const sanitized = unique(
|
||||
next.filter((id) => availableTools.some((tool) => tool.id === id)).concat(autoToolIds)
|
||||
)
|
||||
setIsUpdatingTools(true)
|
||||
void (async () => {
|
||||
try {
|
||||
await updateAgent({ id: agent.id, allowed_tools: sanitized })
|
||||
} finally {
|
||||
setIsUpdatingTools(false)
|
||||
}
|
||||
})()
|
||||
return sanitized
|
||||
})
|
||||
})
|
||||
},
|
||||
[agent, isUpdatingTools, availableTools, autoToolIds, updateAgent]
|
||||
@ -322,7 +328,7 @@ export const AgentToolingSettings: FC<AgentToolingSettingsProps> = ({ agent, upd
|
||||
}
|
||||
|
||||
return (
|
||||
<SettingsContainer>
|
||||
<SettingsContainer ref={containerRef} onScroll={handleScroll}>
|
||||
{contextHolder}
|
||||
<SettingsItem>
|
||||
<SettingsTitle>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user