diff --git a/src/renderer/src/components/DraggableList/index.tsx b/src/renderer/src/components/DraggableList/index.tsx
index 642b12bfd7..3a953115fa 100644
--- a/src/renderer/src/components/DraggableList/index.tsx
+++ b/src/renderer/src/components/DraggableList/index.tsx
@@ -1,3 +1,7 @@
export { default as DraggableList } from './list'
export { useDraggableReorder } from './useDraggableReorder'
-export { default as DraggableVirtualList } from './virtual-list'
+export {
+ default as DraggableVirtualList,
+ type DraggableVirtualListProps,
+ type DraggableVirtualListRef
+} from './virtual-list'
diff --git a/src/renderer/src/components/DraggableList/list.tsx b/src/renderer/src/components/DraggableList/list.tsx
index 3a2cc5b108..b0e87bd2d2 100644
--- a/src/renderer/src/components/DraggableList/list.tsx
+++ b/src/renderer/src/components/DraggableList/list.tsx
@@ -9,13 +9,13 @@ import {
ResponderProvided
} from '@hello-pangea/dnd'
import { droppableReorder } from '@renderer/utils'
-import { List } from 'antd'
-import { FC } from 'react'
+import { FC, HTMLAttributes } from 'react'
interface Props
{
list: T[]
style?: React.CSSProperties
listStyle?: React.CSSProperties
+ listProps?: HTMLAttributes
children: (item: T, index: number) => React.ReactNode
onUpdate: (list: T[]) => void
onDragStart?: OnDragStartResponder
@@ -28,6 +28,7 @@ const DraggableList: FC> = ({
list,
style,
listStyle,
+ listProps,
droppableProps,
onDragStart,
onUpdate,
@@ -50,9 +51,8 @@ const DraggableList: FC> = ({
{(provided) => (
-
{
+
+ {list.map((item, index) => {
const id = item.id || item
return (
@@ -71,8 +71,8 @@ const DraggableList: FC> = ({
)}
)
- }}
- />
+ })}
+
{provided.placeholder}
)}
diff --git a/src/renderer/src/components/DraggableList/virtual-list.tsx b/src/renderer/src/components/DraggableList/virtual-list.tsx
index 69b0ced667..e915eec1fe 100644
--- a/src/renderer/src/components/DraggableList/virtual-list.tsx
+++ b/src/renderer/src/components/DraggableList/virtual-list.tsx
@@ -10,8 +10,19 @@ import {
} from '@hello-pangea/dnd'
import Scrollbar from '@renderer/components/Scrollbar'
import { droppableReorder } from '@renderer/utils'
-import { useVirtualizer } from '@tanstack/react-virtual'
-import { type Key, memo, useCallback, useRef } from 'react'
+import { type ScrollToOptions, useVirtualizer, type VirtualItem } from '@tanstack/react-virtual'
+import { type Key, memo, useCallback, useImperativeHandle, useRef } from 'react'
+
+export interface DraggableVirtualListRef {
+ measure: () => void
+ scrollElement: () => HTMLDivElement | null
+ scrollToOffset: (offset: number, options?: ScrollToOptions) => void
+ scrollToIndex: (index: number, options?: ScrollToOptions) => void
+ resizeItem: (index: number, size: number) => void
+ getTotalSize: () => number
+ getVirtualItems: () => VirtualItem[]
+ getVirtualIndexes: () => number[]
+}
/**
* 泛型 Props,用于配置 DraggableVirtualList。
@@ -31,8 +42,8 @@ import { type Key, memo, useCallback, useRef } from 'react'
* @property {React.ReactNode} [header] 列表头部内容
* @property {(item: T, index: number) => React.ReactNode} children 列表项渲染函数
*/
-interface DraggableVirtualListProps {
- ref?: React.Ref
+export interface DraggableVirtualListProps {
+ ref?: React.Ref
className?: string
style?: React.CSSProperties
scrollerStyle?: React.CSSProperties
@@ -100,9 +111,23 @@ function DraggableVirtualList({
overscan
})
+ useImperativeHandle(
+ ref,
+ () => ({
+ measure: () => virtualizer.measure(),
+ scrollElement: () => virtualizer.scrollElement,
+ scrollToOffset: (offset, options) => virtualizer.scrollToOffset(offset, options),
+ scrollToIndex: (index, options) => virtualizer.scrollToIndex(index, options),
+ resizeItem: (index, size) => virtualizer.resizeItem(index, size),
+ getTotalSize: () => virtualizer.getTotalSize(),
+ getVirtualItems: () => virtualizer.getVirtualItems(),
+ getVirtualIndexes: () => virtualizer.getVirtualIndexes()
+ }),
+ [virtualizer]
+ )
+
return (
diff --git a/src/renderer/src/components/ErrorBoundary.tsx b/src/renderer/src/components/ErrorBoundary.tsx
new file mode 100644
index 0000000000..5bfeaeb620
--- /dev/null
+++ b/src/renderer/src/components/ErrorBoundary.tsx
@@ -0,0 +1,57 @@
+import { formatErrorMessage } from '@renderer/utils/error'
+import { Alert, Button, Space } from 'antd'
+import { ComponentType, ReactNode } from 'react'
+import { ErrorBoundary, FallbackProps } from 'react-error-boundary'
+import { useTranslation } from 'react-i18next'
+import styled from 'styled-components'
+
+const DefaultFallback: ComponentType = (props: FallbackProps): ReactNode => {
+ const { t } = useTranslation()
+ const { error } = props
+ const debug = async () => {
+ await window.api.devTools.toggle()
+ }
+ const reload = async () => {
+ await window.api.reload()
+ }
+ return (
+
+
+
+
+
+ }
+ />
+
+ )
+}
+
+const ErrorBoundaryCustomized = ({
+ children,
+ fallbackComponent
+}: {
+ children: ReactNode
+ fallbackComponent?: ComponentType
+}) => {
+ return {children}
+}
+
+const ErrorContainer = styled.div`
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 100%;
+ padding: 8px;
+`
+
+export { ErrorBoundaryCustomized as ErrorBoundary }
diff --git a/src/renderer/src/components/Icons/SVGIcon.tsx b/src/renderer/src/components/Icons/SVGIcon.tsx
index 88598bb02e..8cae9c94de 100644
--- a/src/renderer/src/components/Icons/SVGIcon.tsx
+++ b/src/renderer/src/components/Icons/SVGIcon.tsx
@@ -117,7 +117,7 @@ export function BingLogo(props: SVGProps) {
return (