mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-19 06:30:10 +08:00
style: format JSX closing brackets for better readability
This commit is contained in:
parent
8a74356ff5
commit
d442c934ee
@ -13,15 +13,7 @@
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest"
|
||||
},
|
||||
"keywords": [
|
||||
"ai",
|
||||
"sdk",
|
||||
"openai",
|
||||
"anthropic",
|
||||
"google",
|
||||
"cherry-studio",
|
||||
"vercel-ai-sdk"
|
||||
],
|
||||
"keywords": ["ai", "sdk", "openai", "anthropic", "google", "cherry-studio", "vercel-ai-sdk"],
|
||||
"author": "Cherry Studio",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@ -56,9 +48,7 @@
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"files": ["dist"],
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
|
||||
@ -24,7 +24,6 @@ export const googleToolsPlugin = (config?: ToolConfig) =>
|
||||
if (!typedParams.tools) {
|
||||
typedParams.tools = {}
|
||||
}
|
||||
|
||||
// 使用类型安全的方式遍历配置
|
||||
;(Object.keys(config) as ToolConfigKey[]).forEach((key) => {
|
||||
if (config[key] && key in toolNameMap && key in google.tools) {
|
||||
|
||||
@ -1,26 +1,21 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"declaration": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"esModuleInterop": true,
|
||||
"experimentalDecorators": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"declaration": true,
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"noEmitOnError": false,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true
|
||||
"outDir": "./dist",
|
||||
"resolveJsonModule": true,
|
||||
"rootDir": "./src",
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"target": "ES2020"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist"
|
||||
]
|
||||
}
|
||||
"exclude": ["node_modules", "dist"],
|
||||
"include": ["src/**/*"]
|
||||
}
|
||||
|
||||
@ -3,10 +3,7 @@
|
||||
"description": "table extension for tiptap forked from tiptap/extension-table",
|
||||
"version": "3.0.11",
|
||||
"homepage": "https://cherry-ai.com",
|
||||
"keywords": [
|
||||
"tiptap",
|
||||
"tiptap extension"
|
||||
],
|
||||
"keywords": ["tiptap", "tiptap extension"],
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
@ -62,10 +59,7 @@
|
||||
"main": "dist/index.cjs",
|
||||
"module": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"files": [
|
||||
"src",
|
||||
"dist"
|
||||
],
|
||||
"files": ["src", "dist"],
|
||||
"devDependencies": {
|
||||
"@tiptap/core": "^3.2.0",
|
||||
"@tiptap/pm": "^3.2.0",
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
.command-list-popover {
|
||||
/* Base styles are handled inline for theme support */
|
||||
|
||||
/* Arrow styles based on placement */
|
||||
}
|
||||
|
||||
|
||||
@ -25,7 +25,8 @@ const EmojiAvatar = ({
|
||||
$fontSize={fontSize ?? size * 0.5}
|
||||
onClick={onClick}
|
||||
className={className}
|
||||
style={style}>
|
||||
style={style}
|
||||
>
|
||||
{children}
|
||||
</StyledEmojiAvatar>
|
||||
)
|
||||
|
||||
@ -25,7 +25,8 @@ const ModelAvatar: FC<Props> = ({ model, size, props, className }) => {
|
||||
justifyContent: 'center'
|
||||
}}
|
||||
{...props}
|
||||
className={className}>
|
||||
className={className}
|
||||
>
|
||||
{first(model?.name)}
|
||||
</Avatar>
|
||||
)
|
||||
|
||||
@ -82,21 +82,24 @@ const HtmlArtifactsPopup: React.FC<HtmlArtifactsPopupProps> = ({ open, title, ht
|
||||
size="small"
|
||||
type={viewMode === 'split' ? 'primary' : 'default'}
|
||||
icon={<SquareSplitHorizontal size={14} />}
|
||||
onClick={() => setViewMode('split')}>
|
||||
onClick={() => setViewMode('split')}
|
||||
>
|
||||
{t('html_artifacts.split')}
|
||||
</ViewButton>
|
||||
<ViewButton
|
||||
size="small"
|
||||
type={viewMode === 'code' ? 'primary' : 'default'}
|
||||
icon={<Code size={14} />}
|
||||
onClick={() => setViewMode('code')}>
|
||||
onClick={() => setViewMode('code')}
|
||||
>
|
||||
{t('html_artifacts.code')}
|
||||
</ViewButton>
|
||||
<ViewButton
|
||||
size="small"
|
||||
type={viewMode === 'preview' ? 'primary' : 'default'}
|
||||
icon={<Eye size={14} />}
|
||||
onClick={() => setViewMode('preview')}>
|
||||
onClick={() => setViewMode('preview')}
|
||||
>
|
||||
{t('html_artifacts.preview')}
|
||||
</ViewButton>
|
||||
</ViewControls>
|
||||
@ -120,7 +123,8 @@ const HtmlArtifactsPopup: React.FC<HtmlArtifactsPopupProps> = ({ open, title, ht
|
||||
onClick: () => handleCapture('clipboard')
|
||||
}
|
||||
]
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<Tooltip title={t('html_artifacts.capture.label')} mouseLeaveDelay={0}>
|
||||
<Button type="text" icon={<Camera size={16} />} className="nodrag" />
|
||||
</Tooltip>
|
||||
@ -230,7 +234,8 @@ const HtmlArtifactsPopup: React.FC<HtmlArtifactsPopupProps> = ({ open, title, ht
|
||||
}}
|
||||
zIndex={isFullscreen ? 10000 : 1000}
|
||||
footer={null}
|
||||
closable={false}>
|
||||
closable={false}
|
||||
>
|
||||
<Container>{renderContent()}</Container>
|
||||
</StyledModal>
|
||||
)
|
||||
|
||||
@ -295,7 +295,8 @@ export const CodeBlockView: React.FC<Props> = memo(({ children, language, onSave
|
||||
<SplitViewWrapper
|
||||
className="split-view-wrapper"
|
||||
$isSpecialView={showSpecialView && !showSourceView}
|
||||
$isSplitView={showSpecialView && showSourceView}>
|
||||
$isSplitView={showSpecialView && showSourceView}
|
||||
>
|
||||
{showSpecialView && specialView}
|
||||
{showSourceView && sourceView}
|
||||
</SplitViewWrapper>
|
||||
|
||||
@ -29,7 +29,8 @@ const CodeToolButton = ({ tool }: CodeToolButtonProps) => {
|
||||
onClick: child.onClick
|
||||
}))
|
||||
}}
|
||||
trigger={['click']}>
|
||||
trigger={['click']}
|
||||
>
|
||||
{mainTool}
|
||||
</Dropdown>
|
||||
)
|
||||
|
||||
@ -168,14 +168,16 @@ const CodeViewer = ({
|
||||
maxHeight: expanded ? undefined : maxHeight,
|
||||
overflowY: expanded ? 'hidden' : 'auto'
|
||||
} as React.CSSProperties
|
||||
}>
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="shiki-list"
|
||||
style={{
|
||||
height: `${virtualizer.getTotalSize()}px`,
|
||||
width: '100%',
|
||||
position: 'relative'
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
@ -183,7 +185,8 @@ const CodeViewer = ({
|
||||
left: 0,
|
||||
width: '100%',
|
||||
transform: `translateY(${virtualItems[0]?.start ?? 0}px)`
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{virtualItems.map((virtualItem) => (
|
||||
<div key={virtualItem.key} data-index={virtualItem.index} ref={virtualizer.measureElement}>
|
||||
<VirtualizedRow
|
||||
|
||||
@ -58,7 +58,8 @@ const CollapsibleSearchBar = ({
|
||||
expanded: { maxWidth: maxWidth, opacity: 1, transition: { duration: 0.3, ease: 'easeInOut' } },
|
||||
collapsed: { maxWidth: 0, opacity: 0, transition: { duration: 0.3, ease: 'easeInOut' } }
|
||||
}}
|
||||
style={{ overflow: 'hidden', flex: 1 }}>
|
||||
style={{ overflow: 'hidden', flex: 1 }}
|
||||
>
|
||||
<Input
|
||||
ref={inputRef}
|
||||
type="text"
|
||||
@ -91,7 +92,8 @@ const CollapsibleSearchBar = ({
|
||||
hidden: { opacity: 0, transition: { duration: 0.1, ease: 'easeInOut' } }
|
||||
}}
|
||||
style={{ cursor: 'pointer', display: 'flex' }}
|
||||
onClick={() => setSearchVisible(true)}>
|
||||
onClick={() => setSearchVisible(true)}
|
||||
>
|
||||
<Tooltip title={tooltip} mouseEnterDelay={0.5} mouseLeaveDelay={0}>
|
||||
{icon}
|
||||
</Tooltip>
|
||||
|
||||
@ -350,7 +350,8 @@ export const ContentSearch = React.forwardRef<ContentSearchRef, Props>(
|
||||
<Container
|
||||
ref={containerRef}
|
||||
style={enableContentSearch ? {} : { display: 'none' }}
|
||||
$overlayPosition={positionMode === 'absolute' ? 'absolute' : 'static'}>
|
||||
$overlayPosition={positionMode === 'absolute' ? 'absolute' : 'static'}
|
||||
>
|
||||
<NarrowLayout style={{ width: '100%' }}>
|
||||
<SearchBarContainer $position={positionMode}>
|
||||
<InputWrapper>
|
||||
|
||||
@ -153,7 +153,8 @@ describe('DraggableVirtualList', () => {
|
||||
onUpdate={() => {}}
|
||||
className="custom-class"
|
||||
style={{ border: '1px solid red' }}
|
||||
itemStyle={{ background: 'blue' }}>
|
||||
itemStyle={{ background: 'blue' }}
|
||||
>
|
||||
{(item) => <div>{item.name}</div>}
|
||||
</DraggableVirtualList>
|
||||
)
|
||||
|
||||
@ -78,7 +78,8 @@ function DraggableList<T>({
|
||||
...listStyle,
|
||||
...provided.draggableProps.style,
|
||||
marginBottom: 8
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{children(item, index)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -129,7 +129,8 @@ function DraggableVirtualList<T>({
|
||||
return (
|
||||
<div
|
||||
className={`${className} draggable-virtual-list`}
|
||||
style={{ height: '100%', display: 'flex', flexDirection: 'column', ...style }}>
|
||||
style={{ height: '100%', display: 'flex', flexDirection: 'column', ...style }}
|
||||
>
|
||||
<DragDropContext onDragStart={onDragStart} onDragEnd={_onDragEnd}>
|
||||
{header}
|
||||
<Droppable
|
||||
@ -145,12 +146,14 @@ function DraggableVirtualList<T>({
|
||||
style={{
|
||||
...itemStyle,
|
||||
...provided.draggableProps.style
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{item && children(item, rubric.source.index)}
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
{...droppableProps}>
|
||||
{...droppableProps}
|
||||
>
|
||||
{(provided) => {
|
||||
// 让 dnd 和虚拟列表共享同一个滚动容器
|
||||
const setRefs = (el: HTMLDivElement | null) => {
|
||||
@ -169,14 +172,16 @@ function DraggableVirtualList<T>({
|
||||
width: '100%',
|
||||
overflowY: 'auto',
|
||||
position: 'relative'
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="virtual-list"
|
||||
style={{
|
||||
height: `${virtualizer.getTotalSize()}px`,
|
||||
width: '100%',
|
||||
position: 'relative'
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{virtualizer.getVirtualItems().map((virtualItem) => (
|
||||
<VirtualRow
|
||||
key={virtualItem.key}
|
||||
@ -211,7 +216,8 @@ const VirtualRow = memo(
|
||||
key={`draggable_${draggableId}`}
|
||||
draggableId={draggableId}
|
||||
isDragDisabled={disabled}
|
||||
index={virtualItem.index}>
|
||||
index={virtualItem.index}
|
||||
>
|
||||
{(provided) => {
|
||||
const setDragRefs = (el: HTMLElement | null) => {
|
||||
provided.innerRef(el)
|
||||
@ -242,7 +248,8 @@ const VirtualRow = memo(
|
||||
left: 0,
|
||||
width: '100%',
|
||||
transform: combinedTransform
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<div {...provided.dragHandleProps} className="draggable-content" style={itemStyle}>
|
||||
{item && children(item, virtualItem.index)}
|
||||
</div>
|
||||
|
||||
@ -46,7 +46,8 @@ export const FreeTrialModelTag: FC<Props> = ({ model, showLabel = true }) => {
|
||||
color="var(--color-link)"
|
||||
size={11}
|
||||
onClick={onNavigateProvider}
|
||||
style={{ display: 'flex', alignItems: 'center', gap: 2 }}>
|
||||
style={{ display: 'flex', alignItems: 'center', gap: 2 }}
|
||||
>
|
||||
{getProviderLabel(providerId)}
|
||||
<ArrowUpRight size={12} />
|
||||
</CustomTag>
|
||||
|
||||
@ -69,7 +69,8 @@ export const useHealthStatus = ({ results, showLatency = false }: UseHealthStatu
|
||||
listStyleType: 'none',
|
||||
maxWidth: '300px',
|
||||
wordWrap: 'break-word'
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{results.map((result, idx) => {
|
||||
const statusText = getStatusText(result.status)
|
||||
const statusColor =
|
||||
|
||||
@ -98,7 +98,8 @@ const HorizontalScrollContainer: React.FC<HorizontalScrollContainerProps> = ({
|
||||
className={className}
|
||||
$expandable={expandable}
|
||||
$disableHoverButton={isScrolledToEnd}
|
||||
onClick={expandable ? handleContainerClick : undefined}>
|
||||
onClick={expandable ? handleContainerClick : undefined}
|
||||
>
|
||||
<ScrollContent ref={scrollRef} $gap={gap} $isExpanded={isExpanded} $expandable={expandable}>
|
||||
{children}
|
||||
</ScrollContent>
|
||||
|
||||
@ -48,7 +48,8 @@ const BaseFileIcon = ({ size = '1.1em', text = 'SVG', ...props }: BaseFileIconPr
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}>
|
||||
{...props}
|
||||
>
|
||||
<defs id="defs4" />
|
||||
<path d="m 14,2 v 4 a 2,2 0 0 0 2,2 h 4" id="path3" />
|
||||
<path d="M 15,2 H 6 A 2,2 0 0 0 4,4 v 16 a 2,2 0 0 0 2,2 h 12 a 2,2 0 0 0 2,-2 V 7 Z" id="path4" />
|
||||
@ -58,7 +59,8 @@ const BaseFileIcon = ({ size = '1.1em', text = 'SVG', ...props }: BaseFileIconPr
|
||||
x="12.478625"
|
||||
y="17.170216"
|
||||
id="text4"
|
||||
transform="scale(0.96196394,1.03954)">
|
||||
transform="scale(0.96196394,1.03954)"
|
||||
>
|
||||
<tspan id="tspan4" x="12.478625" y="17.170216" style={tspanStyle}>
|
||||
{text}
|
||||
</tspan>
|
||||
|
||||
@ -17,14 +17,16 @@ export function NutstoreIcon(props: React.SVGProps<SVGSVGElement>) {
|
||||
viewBox="0 0 20 20"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink">
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
<title>线性单坚果</title>
|
||||
<g id="线性单坚果" stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
|
||||
<path
|
||||
d="M10.1590439,0.886175571 C10.1753674,0.890326544 10.291709,0.910777855 10.428428,0.935202765 L10.6388345,0.973279488 C10.7074276,0.985937901 10.77116,0.998048871 10.8200766,1.00807156 C11.2437905,1.09488771 11.6662387,1.21011472 12.1133986,1.37210166 C13.2580363,1.78675499 14.3714894,2.43940777 15.4224927,3.39703693 L15.621,3.584 L15.6351722,3.57092562 C16.53166,2.76294504 17.6751418,2.31986999 18.4291849,2.58060734 L18.5580792,2.63399481 C18.9455012,2.81584984 19.2328582,3.16284846 19.437028,3.61729231 C19.5709871,3.91546021 19.6526725,4.21929758 19.6985752,4.50662941 C19.7148596,4.80478115 19.5904581,5.0358501 19.4098118,5.1582622 C19.3815042,5.17858714 19.3523426,5.19648783 19.3224017,5.21197531 C19.1152073,5.31915066 18.9086763,5.30466603 18.6939183,5.22086872 C18.6620576,5.20843687 18.6328325,5.19564599 18.6006654,5.18105502 C18.4394695,5.11546938 18.2846309,5.06753532 18.1365915,5.04232952 C17.7415971,4.96197402 17.3578102,5.06378907 17.051656,5.32621284 L17.046624,5.33098744 L17.1856424,5.55157847 C18.0964209,7.0577136 18.6880009,8.98631362 18.5914984,10.988329 L18.5672508,11.3423168 C18.518886,12.3590196 18.336046,13.2889191 17.9959883,14.1391815 C17.4227031,15.6418626 16.5311196,16.5912538 15.4105898,16.2529712 L15.278,16.207 C15.204042,16.2889459 15.1247235,16.3618831 15.0410669,16.4278107 L14.9126231,16.5212291 C13.2906651,17.9150353 10.9315401,19.0281897 7.99389616,19.2 L7.17106258,19.2 C3.43360072,19.2 1.02132454,17.63803 0.534391412,16.0333683 L0.513,15.954 L0.504265285,15.9449232 C-0.110228462,15.1972878 0.264421351,10.4760569 2.09599684,6.99794495 L2.22026541,6.76796973 C2.29571954,6.63016882 2.43695112,6.39220857 2.63659846,6.08729923 C2.9688861,5.57981633 3.34471126,5.07232148 3.75709487,4.59788661 C4.2749895,4.0020645 4.81413532,3.50121679 5.3386949,3.15177019 C5.36355777,3.12648036 5.4278064,3.07827062 5.50910569,3.02364741 L5.559,2.991 L5.5530361,2.96941337 C5.48899059,2.69876461 5.47862138,2.4784725 5.54146387,2.2521942 L5.58811106,2.11525813 C5.68308256,1.86409186 5.94349142,1.57994703 6.25873284,1.38755406 C6.58654657,1.18748816 7.23187921,0.95895859 7.69473739,0.883035787 C8.37505518,0.763266442 9.38159553,0.78076773 10.1590439,0.886175571 Z M6.59801776,3.85068129 C6.46732353,3.85068129 6.2240354,3.97828097 6.07844768,4.1001814 C5.59811888,4.42589962 5.12194443,4.87010868 4.65860433,5.40361803 C4.52372819,5.55892011 4.37448327,5.74624534 4.22515758,5.94252901 L4.04684241,6.18089332 C3.57610889,6.82012555 3.16307203,7.45661922 3.27592159,7.33459023 C1.39280393,10.7336939 1.18786427,14.1190682 1.66513528,15.5784041 C1.72944314,15.8645824 2.24255786,16.4352772 2.98506717,16.8902532 C4.03558482,17.5339627 5.43381914,17.9303112 7.15636912,17.9630362 L7.95282724,17.9633776 C10.5671194,17.8104156 12.6011819,16.8513512 14.1270746,15.5866906 L14.2005419,15.5269075 L14.2189125,15.5136158 C14.591184,15.2751975 14.6855045,14.9945722 14.5299888,14.3127204 C14.1480256,12.8500475 13.2023047,10.9705228 11.4802274,8.76564869 C10.6761315,7.73569508 9.84271439,6.77270459 8.9812637,5.88185595 C8.26651717,5.13999817 7.48191474,4.46126051 6.65303256,3.86947602 C6.6343697,3.85523851 6.62003281,3.85068129 6.59801776,3.85068129 Z M8.0520431,2.14478343 C7.34750556,2.24716005 6.81392621,2.48276912 6.75769294,2.58286729 C6.75315545,2.59094425 6.75172186,2.59912409 6.75788522,2.63367631 L6.761,2.653 C6.92447955,2.67441039 7.07755879,2.72514333 7.22081781,2.80306173 L7.36053304,2.88992896 C8.25106173,3.52400396 9.08393795,4.2496146 9.84209216,5.05104835 C10.7498631,5.98954517 11.620838,6.99715009 12.4127624,8.02643665 C14.2357617,10.3660968 15.255676,12.4067536 15.6810213,14.0171728 C15.7810435,14.3986973 15.8140553,14.7531702 15.7838468,15.0855202 L15.779624,15.1139874 L15.7923351,15.1170186 C16.0195271,15.1453183 16.2337261,14.9383655 16.4514,14.5090146 L16.5168229,14.3735502 C16.5998938,14.1934825 16.8522658,13.5389313 16.8131724,13.6336744 L16.800624,13.6629874 L16.8933423,13.4088509 C17.1021765,12.7846983 17.2487406,12.0003637 17.2861365,11.2776414 C17.4525549,9.34169753 16.8847303,7.51332101 15.9618076,5.9792161 C15.8725231,5.8278532 15.7620551,5.66138642 15.6942132,5.57820575 C14.7595226,4.31701776 13.5999579,3.42705248 12.3136888,2.84260842 C11.4827868,2.46507019 10.794487,2.2853603 10.1559862,2.18983638 C9.43796126,2.09113972 8.59553714,2.05880421 8.0520431,2.14478343 Z M16.4823653,4.32067121 L16.364,4.418 L16.393,4.454 L16.5100007,4.3621392 C17.0306065,3.97118443 17.6106194,3.7900296 18.1665334,3.88918284 L18.233,3.904 L18.2063581,3.87419362 C18.1376794,3.79892884 18.0675642,3.72412847 18.0165076,3.68190508 L17.972563,3.65173005 C17.800955,3.56958653 17.0606024,3.86572493 16.4823653,4.32067121 Z"
|
||||
id="形状结合"
|
||||
fill="currentColor"
|
||||
fillRule="nonzero"></path>
|
||||
fillRule="nonzero"
|
||||
></path>
|
||||
</g>
|
||||
</svg>
|
||||
</IconSpan>
|
||||
|
||||
@ -29,7 +29,8 @@ export function MdiLightbulbOffOutline(props: SVGProps<SVGSVGElement>) {
|
||||
{/* Icon from Material Design Icons by Pictogrammers - https://github.com/Templarian/MaterialDesign/blob/master/LICENSE */}
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12 2C9.76 2 7.78 3.05 6.5 4.68l1.43 1.43C8.84 4.84 10.32 4 12 4a5 5 0 0 1 5 5c0 1.68-.84 3.16-2.11 4.06l1.42 1.44C17.94 13.21 19 11.24 19 9a7 7 0 0 0-7-7M3.28 4L2 5.27L5.04 8.3C5 8.53 5 8.76 5 9c0 2.38 1.19 4.47 3 5.74V17a1 1 0 0 0 1 1h5.73l4 4L20 20.72zm3.95 6.5l5.5 5.5H10v-2.42a5 5 0 0 1-2.77-3.08M9 20v1a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1v-1z"></path>
|
||||
d="M12 2C9.76 2 7.78 3.05 6.5 4.68l1.43 1.43C8.84 4.84 10.32 4 12 4a5 5 0 0 1 5 5c0 1.68-.84 3.16-2.11 4.06l1.42 1.44C17.94 13.21 19 11.24 19 9a7 7 0 0 0-7-7M3.28 4L2 5.27L5.04 8.3C5 8.53 5 8.76 5 9c0 2.38 1.19 4.47 3 5.74V17a1 1 0 0 0 1 1h5.73l4 4L20 20.72zm3.95 6.5l5.5 5.5H10v-2.42a5 5 0 0 1-2.77-3.08M9 20v1a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1v-1z"
|
||||
></path>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
@ -40,7 +41,8 @@ export function MdiLightbulbAutoOutline(props: SVGProps<SVGSVGElement>) {
|
||||
{/* Icon from Material Design Icons by Pictogrammers - https://github.com/Templarian/MaterialDesign/blob/master/LICENSE */}
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M9 2c3.87 0 7 3.13 7 7c0 2.38-1.19 4.47-3 5.74V17c0 .55-.45 1-1 1H6c-.55 0-1-.45-1-1v-2.26C3.19 13.47 2 11.38 2 9c0-3.87 3.13-7 7-7M6 21v-1h6v1c0 .55-.45 1-1 1H7c-.55 0-1-.45-1-1M9 4C6.24 4 4 6.24 4 9c0 2.05 1.23 3.81 3 4.58V16h4v-2.42c1.77-.77 3-2.53 3-4.58c0-2.76-2.24-5-5-5m10 9h-2l-3.2 9h1.9l.7-2h3.2l.7 2h1.9zm-2.15 5.65L18 15l1.15 3.65z"></path>
|
||||
d="M9 2c3.87 0 7 3.13 7 7c0 2.38-1.19 4.47-3 5.74V17c0 .55-.45 1-1 1H6c-.55 0-1-.45-1-1v-2.26C3.19 13.47 2 11.38 2 9c0-3.87 3.13-7 7-7M6 21v-1h6v1c0 .55-.45 1-1 1H7c-.55 0-1-.45-1-1M9 4C6.24 4 4 6.24 4 9c0 2.05 1.23 3.81 3 4.58V16h4v-2.42c1.77-.77 3-2.53 3-4.58c0-2.76-2.24-5-5-5m10 9h-2l-3.2 9h1.9l.7-2h3.2l.7 2h1.9zm-2.15 5.65L18 15l1.15 3.65z"
|
||||
></path>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
@ -51,7 +53,8 @@ export function MdiLightbulbOn10(props: SVGProps<SVGSVGElement>) {
|
||||
{/* Icon from Material Design Icons by Pictogrammers - https://github.com/Templarian/MaterialDesign/blob/master/LICENSE */}
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M1 11h3v2H1zm18.1-7.5L17 5.6L18.4 7l2.1-2.1zM11 1h2v3h-2zM4.9 3.5L3.5 4.9L5.6 7L7 5.6zM10 22c0 .6.4 1 1 1h2c.6 0 1-.4 1-1v-1h-4zm2-16c-3.3 0-6 2.7-6 6c0 2.2 1.2 4.2 3 5.2V19c0 .6.4 1 1 1h4c.6 0 1-.4 1-1v-1.8c1.8-1 3-3 3-5.2c0-3.3-2.7-6-6-6m1 9.9V17h-2v-1.1c-1.7-.4-3-2-3-3.9c0-2.2 1.8-4 4-4s4 1.8 4 4c0 1.9-1.3 3.4-3 3.9m7-4.9h3v2h-3z"></path>
|
||||
d="M1 11h3v2H1zm18.1-7.5L17 5.6L18.4 7l2.1-2.1zM11 1h2v3h-2zM4.9 3.5L3.5 4.9L5.6 7L7 5.6zM10 22c0 .6.4 1 1 1h2c.6 0 1-.4 1-1v-1h-4zm2-16c-3.3 0-6 2.7-6 6c0 2.2 1.2 4.2 3 5.2V19c0 .6.4 1 1 1h4c.6 0 1-.4 1-1v-1.8c1.8-1 3-3 3-5.2c0-3.3-2.7-6-6-6m1 9.9V17h-2v-1.1c-1.7-.4-3-2-3-3.9c0-2.2 1.8-4 4-4s4 1.8 4 4c0 1.9-1.3 3.4-3 3.9m7-4.9h3v2h-3z"
|
||||
></path>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
@ -74,7 +77,8 @@ export function MdiLightbulbOn50(props: SVGProps<SVGSVGElement>) {
|
||||
{/* Icon from Material Design Icons by Pictogrammers - https://github.com/Templarian/MaterialDesign/blob/master/LICENSE */}
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M1 11h3v2H1zm9 11c0 .6.4 1 1 1h2c.6 0 1-.4 1-1v-1h-4zm3-21h-2v3h2zM4.9 3.5L3.5 4.9L5.6 7L7 5.6zM20 11v2h3v-2zm-.9-7.5L17 5.6L18.4 7l2.1-2.1zM18 12c0 2.2-1.2 4.2-3 5.2V19c0 .6-.4 1-1 1h-4c-.6 0-1-.4-1-1v-1.8c-1.8-1-3-3-3-5.2c0-3.3 2.7-6 6-6s6 2.7 6 6M8 12c0 .35.05.68.14 1h7.72c.09-.32.14-.65.14-1c0-2.21-1.79-4-4-4s-4 1.79-4 4"></path>
|
||||
d="M1 11h3v2H1zm9 11c0 .6.4 1 1 1h2c.6 0 1-.4 1-1v-1h-4zm3-21h-2v3h2zM4.9 3.5L3.5 4.9L5.6 7L7 5.6zM20 11v2h3v-2zm-.9-7.5L17 5.6L18.4 7l2.1-2.1zM18 12c0 2.2-1.2 4.2-3 5.2V19c0 .6-.4 1-1 1h-4c-.6 0-1-.4-1-1v-1.8c-1.8-1-3-3-3-5.2c0-3.3 2.7-6 6-6s6 2.7 6 6M8 12c0 .35.05.68.14 1h7.72c.09-.32.14-.65.14-1c0-2.21-1.79-4-4-4s-4 1.79-4 4"
|
||||
></path>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
@ -96,7 +100,8 @@ export function MdiLightbulbOn90(props: SVGProps<SVGSVGElement>) {
|
||||
{/* Icon from Material Design Icons by Pictogrammers - https://github.com/Templarian/MaterialDesign/blob/master/LICENSE */}
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M7 5.6L5.6 7L3.5 4.9l1.4-1.4zM10 22c0 .6.4 1 1 1h2c.6 0 1-.4 1-1v-1h-4zm-9-9h3v-2H1zM13 1h-2v3h2zm7 10v2h3v-2zm-.9-7.5L17 5.6L18.4 7l2.1-2.1zM18 12c0 2.2-1.2 4.2-3 5.2V19c0 .6-.4 1-1 1h-4c-.6 0-1-.4-1-1v-1.8c-1.8-1-3-3-3-5.2c0-3.3 2.7-6 6-6s6 2.7 6 6m-6-4c-1 0-1.91.38-2.61 1h5.22C13.91 8.38 13 8 12 8"></path>
|
||||
d="M7 5.6L5.6 7L3.5 4.9l1.4-1.4zM10 22c0 .6.4 1 1 1h2c.6 0 1-.4 1-1v-1h-4zm-9-9h3v-2H1zM13 1h-2v3h2zm7 10v2h3v-2zm-.9-7.5L17 5.6L18.4 7l2.1-2.1zM18 12c0 2.2-1.2 4.2-3 5.2V19c0 .6-.4 1-1 1h-4c-.6 0-1-.4-1-1v-1.8c-1.8-1-3-3-3-5.2c0-3.3 2.7-6 6-6s6 2.7 6 6m-6-4c-1 0-1.91.38-2.61 1h5.22C13.91 8.38 13 8 12 8"
|
||||
></path>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
@ -122,7 +127,8 @@ export function BingLogo(props: SVGProps<SVGSVGElement>) {
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}>
|
||||
{...props}
|
||||
>
|
||||
<path d="M4.842.005a.966.966 0 01.604.142l2.62 1.813c.369.256.492.352.637.496.471.47.752 1.09.797 1.765l.008.847.003 1.441.004 13.002.144-.094 7.015-4.353.015.003.029.01c-.398-.17-.893-.339-1.655-.566l-.484-.146c-.584-.18-.71-.238-.921-.38a2.009 2.009 0 01-.37-.312 2.172 2.172 0 01-.41-.592L11.32 9.063c-.166-.444-.166-.49-.156-.63a.92.92 0 01.806-.864l.094-.01c.044-.005.22.023.29.044l.052.021c.06.026.16.075.313.154l3.63 1.908a6.626 6.626 0 013.292 4.531c.194.99.159 2.037-.102 3.012-.216.805-.639 1.694-1.054 2.213l-.08.099-.047.05c-.01.01-.013.01-.01.002l.043-.074-.072.114c-.011.031-.233.28-.38.425l-.17.161c-.22.202-.431.36-.832.62L13.544 23c-.941.6-1.86.912-2.913.992-.23.018-.854.008-1.074-.017a6.31 6.31 0 01-1.658-.412c-1.854-.738-3.223-2.288-3.705-4.195a8.077 8.077 0 01-.121-.57l-.046-.325a1.123 1.123 0 01-.014-.168l-.006-.029L4 11.617 4.01.866a.981.981 0 01.007-.111.943.943 0 01.825-.75z"></path>
|
||||
</svg>
|
||||
)
|
||||
@ -198,11 +204,13 @@ export function ExaLogo(props: SVGProps<SVGSVGElement>) {
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}>
|
||||
{...props}
|
||||
>
|
||||
<title>Exa</title>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M3 0h19v1.791L13.892 12 22 22.209V24H3V0zm9.62 10.348l6.589-8.557H6.03l6.59 8.557zM5.138 3.935v7.17h5.52l-5.52-7.17zm5.52 8.96h-5.52v7.17l5.52-7.17zM6.03 22.21l6.59-8.557 6.589 8.557H6.03z"></path>
|
||||
d="M3 0h19v1.791L13.892 12 22 22.209V24H3V0zm9.62 10.348l6.589-8.557H6.03l6.59 8.557zM5.138 3.935v7.17h5.52l-5.52-7.17zm5.52 8.96h-5.52v7.17l5.52-7.17zM6.03 22.21l6.59-8.557 6.589 8.557H6.03z"
|
||||
></path>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
@ -260,16 +268,19 @@ export function PoeLogo(props: SVGProps<SVGSVGElement>) {
|
||||
width="1em"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}>
|
||||
{...props}
|
||||
>
|
||||
<title>Poe</title>
|
||||
<path d="M20.708 6.876a1.412 1.412 0 00-1.029-.415h-.006a2.019 2.019 0 01-2.02-2.023A1.415 1.415 0 0016.254 3H4.871A1.412 1.412 0 003.47 4.434a2.026 2.026 0 01-2.025 2.025v.002A1.414 1.414 0 000 7.883v3.642a1.414 1.414 0 001.444 1.42 2.025 2.025 0 012.025 2.02v3.693a.5.5 0 00.89.313l2.051-2.567h9.843a1.412 1.412 0 001.4-1.434v-.002c0-1.12.904-2.025 2.026-2.025a1.412 1.412 0 001.446-1.42V7.88c0-.363-.14-.727-.417-1.005zm-2.42 4.687a2.025 2.025 0 01-2.025 2.005H4.861a2.025 2.025 0 01-2.025-2.005v-3.72A2.026 2.026 0 014.86 5.838h11.4a2.026 2.026 0 012.026 2.005v3.72h.002z"></path>
|
||||
<path d="M7.413 7.57A1.422 1.422 0 005.99 8.99v1.422a1.422 1.422 0 102.844 0V8.99c0-.784-.636-1.422-1.422-1.422zm6.297 0a1.422 1.422 0 00-1.422 1.421v1.422a1.422 1.422 0 102.844 0V8.99c0-.784-.636-1.422-1.422-1.422z"></path>
|
||||
<path
|
||||
d="M7.292 22.643l1.993-2.492h9.844a1.413 1.413 0 001.4-1.434 2.025 2.025 0 012.017-2.027h.01A1.409 1.409 0 0024 15.27v-3.594c0-.344-.113-.68-.324-.951l-.397-.519v4.127a1.415 1.415 0 01-1.444 1.42h-.007a2.026 2.026 0 00-2.018 2.025 1.415 1.415 0 01-1.402 1.436H8.565l-2.169 2.712a.574.574 0 00.896.715v.002z"
|
||||
fill="url(#lobe-icons-poe-fill-0)"></path>
|
||||
fill="url(#lobe-icons-poe-fill-0)"
|
||||
></path>
|
||||
<path
|
||||
d="M5.004 19.992l2.12-2.65h9.844a1.414 1.414 0 001.402-1.437c0-1.116.9-2.021 2.014-2.025h.012a1.413 1.413 0 001.443-1.422v-4.13l.52.68c.21.273.324.607.324.95v3.594a1.416 1.416 0 01-1.443 1.42h-.01a2.026 2.026 0 00-2.016 2.026 1.414 1.414 0 01-1.402 1.435H7.97l-1.916 2.4a.671.671 0 01-1.049-.839v-.002z"
|
||||
fill="url(#lobe-icons-poe-fill-1)"></path>
|
||||
fill="url(#lobe-icons-poe-fill-1)"
|
||||
></path>
|
||||
<defs>
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
@ -277,7 +288,8 @@ export function PoeLogo(props: SVGProps<SVGSVGElement>) {
|
||||
x1="34.01"
|
||||
x2="1.086"
|
||||
y1="7.303"
|
||||
y2="27.715">
|
||||
y2="27.715"
|
||||
>
|
||||
<stop stopColor="#46A6F7"></stop>
|
||||
<stop offset="1" stop-color="#8364FF"></stop>
|
||||
</linearGradient>
|
||||
@ -287,7 +299,8 @@ export function PoeLogo(props: SVGProps<SVGSVGElement>) {
|
||||
x1="4.915"
|
||||
x2="24.34"
|
||||
y1="23.511"
|
||||
y2="9.464">
|
||||
y2="9.464"
|
||||
>
|
||||
<stop stopColor="#FF44D3"></stop>
|
||||
<stop offset="1" stop-color="#CF4BFF"></stop>
|
||||
</linearGradient>
|
||||
|
||||
@ -10,11 +10,13 @@ export function SvgSpinners180Ring(props: SVGProps<SVGSVGElement> & { size?: num
|
||||
height={size}
|
||||
viewBox="0 0 24 24"
|
||||
{...svgProps}
|
||||
className={`animation-rotate ${svgProps.className || ''}`.trim()}>
|
||||
className={`animation-rotate ${svgProps.className || ''}`.trim()}
|
||||
>
|
||||
{/* Icon from SVG Spinners by Utkarsh Verma - https://github.com/n3r4zzurr0/svg-spinners/blob/main/LICENSE */}
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M12,4a8,8,0,0,1,7.89,6.7A1.53,1.53,0,0,0,21.38,12h0a1.5,1.5,0,0,0,1.48-1.75,11,11,0,0,0-21.72,0A1.5,1.5,0,0,0,2.62,12h0a1.53,1.53,0,0,0,1.49-1.3A8,8,0,0,1,12,4Z"></path>
|
||||
d="M12,4a8,8,0,0,1,7.89,6.7A1.53,1.53,0,0,0,21.38,12h0a1.5,1.5,0,0,0,1.48-1.75,11,11,0,0,0-21.72,0A1.5,1.5,0,0,0,2.62,12h0a1.53,1.53,0,0,0,1.49-1.3A8,8,0,0,1,12,4Z"
|
||||
></path>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
@ -10,7 +10,8 @@ const UnWrapIcon = (props: React.SVGProps<SVGSVGElement>) => (
|
||||
strokeWidth={2}
|
||||
className="unwrap_svg__lucide unwrap_svg__lucide-text unwrap_svg__size-4"
|
||||
viewBox="0 0 24 24"
|
||||
{...props}>
|
||||
{...props}
|
||||
>
|
||||
<path d="M17 6.1H3M21 12.1H3M15.1 18H3" />
|
||||
</svg>
|
||||
)
|
||||
|
||||
@ -12,7 +12,8 @@ const WrapIcon = (props: React.SVGProps<SVGSVGElement>) => (
|
||||
strokeWidth={2}
|
||||
className="wrap_svg__lucide wrap_svg__lucide-wrap-text wrap_svg__size-4"
|
||||
viewBox="0 0 24 24"
|
||||
{...props}>
|
||||
{...props}
|
||||
>
|
||||
<path d="M3 6h18M3 12h15a3 3 0 1 1 0 6h-4" />
|
||||
<path d="m16 16-2 2 2 2M3 18h7" />
|
||||
</svg>
|
||||
|
||||
@ -199,7 +199,8 @@ export function LocalBackupManager({ visible, onClose, localBackupDir, restoreMe
|
||||
type="link"
|
||||
danger
|
||||
onClick={() => handleDeleteSingle(record.fileName)}
|
||||
disabled={deleting || restoring}>
|
||||
disabled={deleting || restoring}
|
||||
>
|
||||
{t('settings.data.local.backup.manager.delete.text')}
|
||||
</Button>
|
||||
</>
|
||||
@ -232,13 +233,15 @@ export function LocalBackupManager({ visible, onClose, localBackupDir, restoreMe
|
||||
icon={<DeleteOutlined />}
|
||||
onClick={handleDeleteSelected}
|
||||
disabled={selectedRowKeys.length === 0 || deleting}
|
||||
loading={deleting}>
|
||||
loading={deleting}
|
||||
>
|
||||
{t('settings.data.local.backup.manager.delete.selected')} ({selectedRowKeys.length})
|
||||
</Button>,
|
||||
<Button key="close" onClick={onClose}>
|
||||
{t('common.close')}
|
||||
</Button>
|
||||
]}>
|
||||
]}
|
||||
>
|
||||
<Table
|
||||
rowKey="fileName"
|
||||
columns={columns}
|
||||
|
||||
@ -39,7 +39,8 @@ export function LocalBackupModal({
|
||||
<Button key="submit" type="primary" loading={backuping} onClick={handleBackup}>
|
||||
{t('common.confirm')}
|
||||
</Button>
|
||||
]}>
|
||||
]}
|
||||
>
|
||||
<Input
|
||||
value={customFileName}
|
||||
onChange={(e) => setCustomFileName(e.target.value)}
|
||||
|
||||
@ -44,7 +44,8 @@ const MarkdownEditor: FC<MarkdownEditorProps> = ({
|
||||
<PreviewArea className="markdown">
|
||||
<ReactMarkdown
|
||||
remarkPlugins={[remarkGfm, remarkCjkFriendly, remarkMath]}
|
||||
rehypePlugins={[rehypeRaw, rehypeKatex]}>
|
||||
rehypePlugins={[rehypeRaw, rehypeKatex]}
|
||||
>
|
||||
{inputValue || t('settings.provider.notes.markdown_editor_default_value')}
|
||||
</ReactMarkdown>
|
||||
</PreviewArea>
|
||||
|
||||
@ -99,7 +99,8 @@ const MinAppTabsPool: React.FC = () => {
|
||||
: { visibility: 'hidden' }
|
||||
}
|
||||
data-minapp-tabs-pool
|
||||
aria-hidden={!shouldShow}>
|
||||
aria-hidden={!shouldShow}
|
||||
>
|
||||
{apps.map((app) => (
|
||||
<WebviewWrapper key={app.id} $active={app.id === currentMinappId}>
|
||||
<WebviewContainer
|
||||
|
||||
@ -417,7 +417,8 @@ const MinappPopupContainer: React.FC = () => {
|
||||
root: {
|
||||
maxWidth: '400px'
|
||||
}
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<TitleText onContextMenu={(e) => handleCopyUrl(e, url ?? appInfo.url)}>{appInfo.name}</TitleText>
|
||||
</Tooltip>
|
||||
{appInfo.canOpenExternalLink && (
|
||||
@ -431,7 +432,8 @@ const MinappPopupContainer: React.FC = () => {
|
||||
<ButtonsGroup
|
||||
className={isWin || isLinux ? 'windows' : ''}
|
||||
style={{ marginRight: isWin || isLinux ? '140px' : 0 }}
|
||||
isTopNavbar={isTopNavbar}>
|
||||
isTopNavbar={isTopNavbar}
|
||||
>
|
||||
<Tooltip title={t('minapp.popup.goBack')} mouseEnterDelay={0.8} placement="bottom">
|
||||
<TitleButton onClick={() => handleGoBack(appInfo.id)}>
|
||||
<ArrowLeftOutlined />
|
||||
@ -459,7 +461,8 @@ const MinappPopupContainer: React.FC = () => {
|
||||
: t('minapp.add_to_sidebar')
|
||||
}
|
||||
mouseEnterDelay={0.8}
|
||||
placement="bottom">
|
||||
placement="bottom"
|
||||
>
|
||||
<TitleButton onClick={() => handleTogglePin(appInfo.id)} className={appInfo.isPinned ? 'pinned' : ''}>
|
||||
<PushpinOutlined style={{ fontSize: 16 }} />
|
||||
</TitleButton>
|
||||
@ -472,7 +475,8 @@ const MinappPopupContainer: React.FC = () => {
|
||||
: t('minapp.popup.open_link_external_off')
|
||||
}
|
||||
mouseEnterDelay={0.8}
|
||||
placement="bottom">
|
||||
placement="bottom"
|
||||
>
|
||||
<TitleButton onClick={handleToggleOpenExternal} className={minappsOpenLinkExternal ? 'open-external' : ''}>
|
||||
<LinkOutlined />
|
||||
</TitleButton>
|
||||
@ -547,7 +551,8 @@ const MinappPopupContainer: React.FC = () => {
|
||||
body: {
|
||||
borderTopLeftRadius: '10px'
|
||||
}
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{/* 在所有小程序中显示GoogleLoginTip */}
|
||||
<GoogleLoginTip isReady={isReady} currentUrl={currentUrl} currentAppId={currentMinappId} />
|
||||
{!isReady && (
|
||||
|
||||
@ -33,7 +33,8 @@ const ModelIdWithTags = ({
|
||||
</Typography.Text>
|
||||
}
|
||||
mouseEnterDelay={0.5}
|
||||
placement="top">
|
||||
placement="top"
|
||||
>
|
||||
<NameSpan>{model.name}</NameSpan>
|
||||
</Tooltip>
|
||||
<ModelTagsWithLabel model={model} size={11} style={{ flexShrink: 0 }} />
|
||||
|
||||
@ -36,7 +36,7 @@ export const OGCard = ({ link, show }: Props) => {
|
||||
const GeneratedGraph = useCallback(() => {
|
||||
return (
|
||||
<div className="flex h-36 items-center justify-center bg-accent p-4">
|
||||
<h2 className="text-2xl font-bold">{metadata['og:title'] || hostname}</h2>
|
||||
<h2 className="font-bold text-2xl">{metadata['og:title'] || hostname}</h2>
|
||||
</div>
|
||||
)
|
||||
}, [hostname, metadata])
|
||||
@ -67,7 +67,8 @@ export const OGCard = ({ link, show }: Props) => {
|
||||
fontSize: '14px',
|
||||
lineHeight: '1.2',
|
||||
color: 'var(--color-text)'
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{metadata['og:title'] || hostname}
|
||||
</Title>
|
||||
</StyledHyperLink>
|
||||
@ -78,7 +79,8 @@ export const OGCard = ({ link, show }: Props) => {
|
||||
fontSize: '12px',
|
||||
lineHeight: '1.2',
|
||||
color: 'var(--color-text-secondary)'
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{metadata['og:description'] || link}
|
||||
</Paragraph>
|
||||
</PreviewContent>
|
||||
|
||||
@ -316,7 +316,8 @@ const PopupContainer: React.FC<PopupContainerProps> = ({
|
||||
disabled: vaults.length === 0 || loading || !!error
|
||||
}}
|
||||
okText={i18n.t('chat.topics.export.obsidian_btn')}
|
||||
afterClose={() => setOpen(open)}>
|
||||
afterClose={() => setOpen(open)}
|
||||
>
|
||||
{error && <Alert message={error} type="error" showIcon style={{ marginBottom: 16 }} />}
|
||||
<Form layout="horizontal" labelCol={{ span: 6 }} wrapperCol={{ span: 18 }} labelAlign="left">
|
||||
<Form.Item label={i18n.t('chat.topics.export.obsidian_title')}>
|
||||
@ -333,7 +334,8 @@ const PopupContainer: React.FC<PopupContainerProps> = ({
|
||||
value={selectedVault}
|
||||
onChange={handleVaultChange}
|
||||
placeholder={i18n.t('chat.topics.export.obsidian_vault_placeholder')}
|
||||
style={{ width: '100%' }}>
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
{vaults.map((vault) => (
|
||||
<Option key={vault.name} value={vault.name}>
|
||||
{vault.name}
|
||||
@ -363,7 +365,8 @@ const PopupContainer: React.FC<PopupContainerProps> = ({
|
||||
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
|
||||
treeDefaultExpandAll={false}
|
||||
treeNodeFilterProp="title"
|
||||
treeData={fileTreeData}></TreeSelect>
|
||||
treeData={fileTreeData}
|
||||
></TreeSelect>
|
||||
) : (
|
||||
<Empty
|
||||
description={i18n.t('chat.topics.export.obsidian_select_vault_first')}
|
||||
@ -398,7 +401,8 @@ const PopupContainer: React.FC<PopupContainerProps> = ({
|
||||
value={state.processingMethod}
|
||||
onChange={(value) => handleChange('processingMethod', value)}
|
||||
placeholder={i18n.t('chat.topics.export.obsidian_operate_placeholder')}
|
||||
allowClear>
|
||||
allowClear
|
||||
>
|
||||
<Option value={ObsidianProcessingMethod.APPEND}>
|
||||
{i18n.t('chat.topics.export.obsidian_operate_append')}
|
||||
</Option>
|
||||
|
||||
@ -172,7 +172,8 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
}
|
||||
}}
|
||||
closeIcon={null}
|
||||
footer={null}>
|
||||
footer={null}
|
||||
>
|
||||
<HStack style={{ padding: '0 12px', marginTop: 5 }}>
|
||||
<Input
|
||||
prefix={
|
||||
@ -198,7 +199,8 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
key={agent.id}
|
||||
onClick={() => onCreateAssistant(agent)}
|
||||
className={`agent-item ${agent.id === 'default' ? 'default' : ''} ${index === selectedIndex ? 'keyboard-selected' : ''}`}
|
||||
onMouseEnter={() => setSelectedIndex(index)}>
|
||||
onMouseEnter={() => setSelectedIndex(index)}
|
||||
>
|
||||
<HStack alignItems="center" gap={5} style={{ overflow: 'hidden', maxWidth: '100%' }}>
|
||||
<EmojiIcon emoji={agent.emoji || ''} />
|
||||
<span className="text-nowrap">{agent.name}</span>
|
||||
|
||||
@ -127,7 +127,8 @@ const ApiKeyItem: FC<ApiKeyItemProps> = ({
|
||||
mouseEnterDelay={0.5}
|
||||
placement="top"
|
||||
// 确保不留下明文
|
||||
destroyOnHidden>
|
||||
destroyOnHidden
|
||||
>
|
||||
<span style={{ cursor: 'help' }}>{maskApiKey(keyStatus.key)}</span>
|
||||
</Tooltip>
|
||||
|
||||
@ -154,7 +155,8 @@ const ApiKeyItem: FC<ApiKeyItemProps> = ({
|
||||
disabled={disabled}
|
||||
okText={t('common.confirm')}
|
||||
cancelText={t('common.cancel')}
|
||||
okButtonProps={{ danger: true }}>
|
||||
okButtonProps={{ danger: true }}
|
||||
>
|
||||
<Tooltip title={t('common.delete')} mouseLeaveDelay={0}>
|
||||
<Button type="text" icon={<Minus size={16} />} disabled={disabled} />
|
||||
</Tooltip>
|
||||
|
||||
@ -95,7 +95,8 @@ export const ApiKeyList: FC<ApiKeyListProps> = ({ provider, updateProvider, show
|
||||
size="small"
|
||||
type="inner"
|
||||
styles={{ body: { padding: 0 } }}
|
||||
style={{ marginBottom: '5px', border: '0.5px solid var(--color-border)' }}>
|
||||
style={{ marginBottom: '5px', border: '0.5px solid var(--color-border)' }}
|
||||
>
|
||||
{displayKeys.length === 0 ? (
|
||||
<Typography.Text type="secondary" style={{ padding: '4px 11px', display: 'block' }}>
|
||||
{t('error.no_api_key')}
|
||||
@ -138,7 +139,8 @@ export const ApiKeyList: FC<ApiKeyListProps> = ({ provider, updateProvider, show
|
||||
onConfirm={removeInvalidKeys}
|
||||
okText={t('common.confirm')}
|
||||
cancelText={t('common.cancel')}
|
||||
okButtonProps={{ danger: true }}>
|
||||
okButtonProps={{ danger: true }}
|
||||
>
|
||||
<Tooltip title={t('settings.provider.remove_invalid_keys')} placement="top" mouseLeaveDelay={0}>
|
||||
<Button
|
||||
type="text"
|
||||
@ -168,7 +170,8 @@ export const ApiKeyList: FC<ApiKeyListProps> = ({ provider, updateProvider, show
|
||||
onClick={handleAddNew}
|
||||
icon={<Plus size={16} />}
|
||||
autoFocus={shouldAutoFocus()}
|
||||
disabled={isChecking || !!pendingNewKey}>
|
||||
disabled={isChecking || !!pendingNewKey}
|
||||
>
|
||||
{t('common.add')}
|
||||
</Button>
|
||||
</Space>
|
||||
|
||||
@ -50,7 +50,8 @@ const PopupContainer: React.FC<Props> = ({ providerId, title, resolve, showHealt
|
||||
transitionName="animation-move-down"
|
||||
centered
|
||||
width={600}
|
||||
footer={null}>
|
||||
footer={null}
|
||||
>
|
||||
{ListComponent}
|
||||
</Modal>
|
||||
)
|
||||
|
||||
@ -80,7 +80,8 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
okText={t('backup.confirm.button')}
|
||||
maskClosable={false}
|
||||
transitionName="animation-move-down"
|
||||
centered>
|
||||
centered
|
||||
>
|
||||
{!progressData && <div>{t('backup.content')}</div>}
|
||||
{progressData && (
|
||||
<div style={{ textAlign: 'center', padding: '20px 0' }}>
|
||||
|
||||
@ -35,7 +35,8 @@ const PopupContainer: React.FC<Props> = ({ content, resolve, ...rest }) => {
|
||||
afterClose={onClose}
|
||||
transitionName="animation-move-down"
|
||||
centered
|
||||
{...rest}>
|
||||
{...rest}
|
||||
>
|
||||
{content}
|
||||
</Modal>
|
||||
)
|
||||
|
||||
@ -30,7 +30,8 @@ const PopupContainer: React.FC<Props> = ({ resolve, fs }) => {
|
||||
afterClose={onClose}
|
||||
onCancel={onClose}
|
||||
footer={null}
|
||||
centered>
|
||||
centered
|
||||
>
|
||||
<NutstorePathSelector fs={fs} onConfirm={resolve} onCancel={onCancel} />
|
||||
</Modal>
|
||||
)
|
||||
|
||||
@ -67,7 +67,8 @@ const PromptPopupContainer: React.FC<Props> = ({
|
||||
afterClose={onAfterClose}
|
||||
afterOpenChange={handleAfterOpenChange}
|
||||
transitionName="animation-move-down"
|
||||
centered>
|
||||
centered
|
||||
>
|
||||
<Box mb={8}>{message}</Box>
|
||||
<Input.TextArea
|
||||
ref={textAreaRef}
|
||||
|
||||
@ -72,7 +72,8 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
cancelButtonProps={{ disabled: isDisabled }}
|
||||
maskClosable={false}
|
||||
transitionName="animation-move-down"
|
||||
centered>
|
||||
centered
|
||||
>
|
||||
{!progressData && <div>{t('restore.content')}</div>}
|
||||
{progressData && (
|
||||
<div style={{ textAlign: 'center', padding: '20px 0' }}>
|
||||
|
||||
@ -98,7 +98,8 @@ const PopupContainer: React.FC<Props> = ({
|
||||
afterOpenChange={handleAfterOpenChange}
|
||||
maskClosable={false}
|
||||
keyboard={false}
|
||||
centered>
|
||||
centered
|
||||
>
|
||||
<EditorContainer>
|
||||
<RichEditor
|
||||
ref={editorRef}
|
||||
|
||||
@ -303,7 +303,8 @@ const PopupContainer: React.FC<Props> = ({ source, title, resolve }) => {
|
||||
<Form.Item
|
||||
label={t('chat.save.knowledge.select.base.title')}
|
||||
help={!formState.hasValidBase && selectedBaseId ? t('chat.save.knowledge.error.invalid_base') : undefined}
|
||||
validateStatus={!formState.hasValidBase && selectedBaseId ? 'error' : undefined}>
|
||||
validateStatus={!formState.hasValidBase && selectedBaseId ? 'error' : undefined}
|
||||
>
|
||||
<Select
|
||||
value={selectedBaseId}
|
||||
onChange={setSelectedBaseId}
|
||||
@ -319,18 +320,21 @@ const PopupContainer: React.FC<Props> = ({ source, title, resolve }) => {
|
||||
isTopicMode
|
||||
? 'chat.save.topic.knowledge.select.content.label'
|
||||
: 'chat.save.knowledge.select.content.title'
|
||||
)}>
|
||||
)}
|
||||
>
|
||||
<Flex gap={8} style={{ flexDirection: 'column' }}>
|
||||
{contentTypeOptions.map((option) => (
|
||||
<ContentTypeItem
|
||||
key={option.type}
|
||||
align="center"
|
||||
justify="space-between"
|
||||
onClick={() => handleContentTypeToggle(option.type)}>
|
||||
onClick={() => handleContentTypeToggle(option.type)}
|
||||
>
|
||||
<Flex align="center" gap={8}>
|
||||
<CustomTag
|
||||
color={selectedTypes.includes(option.type) ? TAG_COLORS.SELECTED : TAG_COLORS.UNSELECTED}
|
||||
size={12}>
|
||||
size={12}
|
||||
>
|
||||
{option.count}
|
||||
</CustomTag>
|
||||
<span>{option.label}</span>
|
||||
@ -397,7 +401,8 @@ const PopupContainer: React.FC<Props> = ({ source, title, resolve }) => {
|
||||
width={500}
|
||||
okText={t('common.save')}
|
||||
cancelText={t('common.cancel')}
|
||||
okButtonProps={{ loading, disabled: !formState.canSubmit || analysisLoading }}>
|
||||
okButtonProps={{ loading, disabled: !formState.canSubmit || analysisLoading }}
|
||||
>
|
||||
{uiState.type === 'form' ? renderFormContent() : renderEmptyState()}
|
||||
</Modal>
|
||||
)
|
||||
|
||||
@ -49,7 +49,8 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
}}
|
||||
centered
|
||||
closable={false}
|
||||
footer={null}>
|
||||
footer={null}
|
||||
>
|
||||
<HistoryPage />
|
||||
</Modal>
|
||||
)
|
||||
|
||||
@ -374,7 +374,8 @@ const PopupContainer: React.FC<Props> = ({ model, filter: baseFilter, showTagFil
|
||||
selected: item.isSelected
|
||||
})}
|
||||
onClick={() => handleItemClick(item)}
|
||||
onMouseOver={() => !isFocused && setFocusedItemKey(item.key)}>
|
||||
onMouseOver={() => !isFocused && setFocusedItemKey(item.key)}
|
||||
>
|
||||
<ModelItemLeft>
|
||||
{item.icon}
|
||||
{item.name}
|
||||
@ -388,7 +389,8 @@ const PopupContainer: React.FC<Props> = ({ model, filter: baseFilter, showTagFil
|
||||
}
|
||||
}}
|
||||
data-pinned={item.isPinned}
|
||||
$isPinned={item.isPinned}>
|
||||
$isPinned={item.isPinned}
|
||||
>
|
||||
<PushpinOutlined />
|
||||
</PinIconWrapper>
|
||||
</ModelItem>
|
||||
@ -418,7 +420,8 @@ const PopupContainer: React.FC<Props> = ({ model, filter: baseFilter, showTagFil
|
||||
}
|
||||
}}
|
||||
closeIcon={null}
|
||||
footer={null}>
|
||||
footer={null}
|
||||
>
|
||||
{/* 搜索框 */}
|
||||
<SelectModelSearchBar onSearch={setSearchText} />
|
||||
<Divider style={{ margin: 0, marginTop: 4, borderBlockStartWidth: 0.5 }} />
|
||||
@ -440,7 +443,8 @@ const PopupContainer: React.FC<Props> = ({ model, filter: baseFilter, showTagFil
|
||||
isSticky={isSticky}
|
||||
scrollPaddingStart={ITEM_HEIGHT} // 留出 sticky header 高度
|
||||
overscan={5}
|
||||
scrollerStyle={{ pointerEvents: isMouseOver ? 'auto' : 'none' }}>
|
||||
scrollerStyle={{ pointerEvents: isMouseOver ? 'auto' : 'none' }}
|
||||
>
|
||||
{rowRenderer}
|
||||
</DynamicVirtualList>
|
||||
</ListContainer>
|
||||
|
||||
@ -36,7 +36,8 @@ const PopupContainer: React.FC<Props> = ({ title, resolve }) => {
|
||||
onCancel={onCancel}
|
||||
afterClose={onClose}
|
||||
transitionName="animation-move-down"
|
||||
centered>
|
||||
centered
|
||||
>
|
||||
<Box mb={8}>Name</Box>
|
||||
</Modal>
|
||||
)
|
||||
|
||||
@ -135,7 +135,8 @@ const PopupContainer: React.FC<Props> = ({
|
||||
onCancel={onCancel}
|
||||
afterClose={onClose}
|
||||
afterOpenChange={handleAfterOpenChange}
|
||||
centered>
|
||||
centered
|
||||
>
|
||||
<TextAreaContainer>
|
||||
<TextArea
|
||||
ref={textareaRef}
|
||||
@ -151,7 +152,8 @@ const PopupContainer: React.FC<Props> = ({
|
||||
<TranslateButton
|
||||
onClick={handleTranslate}
|
||||
aria-label="Translate text"
|
||||
disabled={isTranslating || !textValue.trim()}>
|
||||
disabled={isTranslating || !textValue.trim()}
|
||||
>
|
||||
{isTranslating ? <LoadingOutlined spin /> : <Languages size={16} />}
|
||||
</TranslateButton>
|
||||
)}
|
||||
|
||||
@ -52,7 +52,8 @@ const PopupContainer: React.FC<Props> = ({ text, title, extension, resolve }) =>
|
||||
}}
|
||||
centered
|
||||
closable={true}
|
||||
footer={null}>
|
||||
footer={null}
|
||||
>
|
||||
{extension !== undefined ? (
|
||||
<Editor
|
||||
editable={false}
|
||||
|
||||
@ -85,7 +85,8 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
} catch (error: any) {
|
||||
window.toast.error(error.message)
|
||||
}
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{t('settings.general.image_upload')}
|
||||
</Upload>
|
||||
</div>
|
||||
@ -100,7 +101,8 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
e.stopPropagation()
|
||||
setEmojiPickerOpen(true)
|
||||
setDropdownOpen(false)
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{t('settings.general.emoji_picker')}
|
||||
</div>
|
||||
)
|
||||
@ -113,7 +115,8 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleReset()
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{t('settings.general.avatar.reset')}
|
||||
</div>
|
||||
)
|
||||
@ -129,7 +132,8 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
onCancel={onCancel}
|
||||
afterClose={onClose}
|
||||
transitionName="animation-move-down"
|
||||
centered>
|
||||
centered
|
||||
>
|
||||
<Center mt="30px">
|
||||
<VStack alignItems="center" gap="10px">
|
||||
<Dropdown
|
||||
@ -143,7 +147,8 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
if (visible) {
|
||||
setEmojiPickerOpen(false)
|
||||
}
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<Popover
|
||||
content={<EmojiPicker onEmojiClick={handleEmojiClick} />}
|
||||
trigger="click"
|
||||
@ -154,7 +159,8 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
setDropdownOpen(false)
|
||||
}
|
||||
}}
|
||||
placement="bottom">
|
||||
placement="bottom"
|
||||
>
|
||||
{isEmoji(avatar) ? (
|
||||
<EmojiAvatar size={80} fontSize={40}>
|
||||
{avatar}
|
||||
|
||||
@ -63,7 +63,8 @@ const SingleFileUploader: React.FC<SingleFileUploaderProps> = ({
|
||||
logger.error('Upload failed: Invalid file format')
|
||||
}
|
||||
}}
|
||||
onRemove={onRemove}>
|
||||
onRemove={onRemove}
|
||||
>
|
||||
<p className="ant-upload-drag-icon">
|
||||
<UploadOutlined />
|
||||
</p>
|
||||
@ -165,7 +166,8 @@ const VideoPopupContainer: React.FC<Props> = ({ title, resolve }) => {
|
||||
width={600}
|
||||
okButtonProps={{ disabled: isOkButtonDisabled }}
|
||||
okText={t('common.confirm')}
|
||||
cancelText={t('common.cancel')}>
|
||||
cancelText={t('common.cancel')}
|
||||
>
|
||||
<Space direction="vertical" style={{ width: '100%', gap: '16px' }}>
|
||||
<SingleFileUploader
|
||||
uploadType="video"
|
||||
|
||||
@ -42,7 +42,8 @@ const GraphvizPreview = ({
|
||||
enableToolbar={enableToolbar}
|
||||
ref={ref}
|
||||
imageRef={containerRef}
|
||||
source="graphviz">
|
||||
source="graphviz"
|
||||
>
|
||||
<ShadowWhiteContainer ref={containerRef} className="graphviz special-preview" />
|
||||
</ImagePreviewLayout>
|
||||
)
|
||||
|
||||
@ -129,7 +129,8 @@ const MermaidPreview = ({
|
||||
enableToolbar={enableToolbar}
|
||||
ref={ref}
|
||||
imageRef={containerRef}
|
||||
source="mermaid">
|
||||
source="mermaid"
|
||||
>
|
||||
<ShadowTransparentContainer ref={containerRef} className="mermaid special-preview" />
|
||||
</ImagePreviewLayout>
|
||||
)
|
||||
|
||||
@ -128,7 +128,8 @@ const PlantUmlPreview = ({
|
||||
enableToolbar={enableToolbar}
|
||||
ref={ref}
|
||||
imageRef={containerRef}
|
||||
source="plantuml">
|
||||
source="plantuml"
|
||||
>
|
||||
<ShadowWhiteContainer ref={containerRef} className="plantuml-preview special-preview" />
|
||||
</ImagePreviewLayout>
|
||||
)
|
||||
|
||||
@ -34,7 +34,8 @@ const SvgPreview = ({ children, enableToolbar = false, className, ref }: SvgPrev
|
||||
enableToolbar={enableToolbar}
|
||||
ref={ref}
|
||||
imageRef={containerRef}
|
||||
source="svg">
|
||||
source="svg"
|
||||
>
|
||||
{/* 使用透明容器,把背景色完全交给 SVG 自己控制 */}
|
||||
<ShadowTransparentContainer ref={containerRef} className={className ?? 'svg-preview special-preview'} />
|
||||
</ImagePreviewLayout>
|
||||
|
||||
@ -79,7 +79,8 @@ export const ProviderAvatarPrimitive: React.FC<ProviderAvatarPrimitiveProps> = (
|
||||
backgroundColor,
|
||||
color,
|
||||
...style
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{getFirstCharacter(providerName)}
|
||||
</ProviderLogo>
|
||||
)
|
||||
|
||||
@ -550,7 +550,8 @@ export const QuickPanelView: React.FC<Props> = ({ setInputText }) => {
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleItemAction(item, 'click')
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<QuickPanelItemLeft>
|
||||
<QuickPanelItemIcon>{item.icon}</QuickPanelItemIcon>
|
||||
<QuickPanelItemLabel>{item.label}</QuickPanelItemLabel>
|
||||
@ -581,7 +582,8 @@ export const QuickPanelView: React.FC<Props> = ({ setInputText }) => {
|
||||
$selectedColorHover={selectedColorHover}
|
||||
$collapsed={collapsed}
|
||||
className={ctx.isVisible ? 'visible' : ''}
|
||||
data-testid="quick-panel">
|
||||
data-testid="quick-panel"
|
||||
>
|
||||
<QuickPanelBody
|
||||
ref={bodyRef}
|
||||
onMouseMove={() =>
|
||||
@ -589,7 +591,8 @@ export const QuickPanelView: React.FC<Props> = ({ setInputText }) => {
|
||||
scrollTriggerRef.current = 'initial'
|
||||
return prev ? prev : true
|
||||
})
|
||||
}>
|
||||
}
|
||||
>
|
||||
{!collapsed && (
|
||||
<DynamicVirtualList
|
||||
ref={listRef}
|
||||
@ -599,7 +602,8 @@ export const QuickPanelView: React.FC<Props> = ({ setInputText }) => {
|
||||
overscan={5}
|
||||
scrollerStyle={{
|
||||
pointerEvents: isMouseOver ? 'auto' : 'none'
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{rowRenderer}
|
||||
</DynamicVirtualList>
|
||||
)}
|
||||
|
||||
@ -161,7 +161,8 @@ const CommandListPopover = ({
|
||||
alignItems: 'center'
|
||||
}}
|
||||
onClick={() => selectItem(index)}
|
||||
onMouseEnter={() => handleItemMouseEnter(index)}>
|
||||
onMouseEnter={() => handleItemMouseEnter(index)}
|
||||
>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '12px', width: '100%' }}>
|
||||
<div
|
||||
style={{
|
||||
@ -171,7 +172,8 @@ const CommandListPopover = ({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<item.icon size={16} />
|
||||
</div>
|
||||
<div style={{ flex: 1, minWidth: 0 }}>
|
||||
|
||||
@ -23,7 +23,8 @@ export const ToCItem: React.FC<ToCItemProps> = ({ item, onItemClick }) => {
|
||||
{
|
||||
'--level': item.level
|
||||
} as React.CSSProperties
|
||||
}>
|
||||
}
|
||||
>
|
||||
<a href={`#${item.id}`} onClick={(e) => onItemClick(e, item.id)} data-item-index={item.itemIndex}>
|
||||
{item.textContent}
|
||||
</a>
|
||||
|
||||
@ -75,7 +75,8 @@ export const ActionMenu: FC<ActionMenuProps> = ({ show, position, items, onClose
|
||||
boxShadow: '0 6px 16px rgba(0,0,0,0.12)',
|
||||
overflow: 'hidden',
|
||||
minWidth
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<Menu selectable={false} items={menuItems} onClick={onMenuClick} style={{ border: 'none' }} />
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -134,7 +134,8 @@ export const ImageUploader: React.FC<ImageUploaderProps> = ({ onImageSelect, vis
|
||||
showUploadList={false}
|
||||
beforeUpload={handleFileSelect}
|
||||
customRequest={() => {}} // Prevent default upload
|
||||
disabled={loading}>
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? (
|
||||
<>
|
||||
<Spin indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />} />
|
||||
@ -180,7 +181,8 @@ export const ImageUploader: React.FC<ImageUploaderProps> = ({ onImageSelect, vis
|
||||
borderRadius: '4px',
|
||||
color: '#3c4043',
|
||||
background: '#ffffff'
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{t('common.clear')}
|
||||
</Button>
|
||||
<Button type="primary" onClick={handleUrlSubmit} disabled={!urlInput.trim()}>
|
||||
@ -199,7 +201,8 @@ export const ImageUploader: React.FC<ImageUploaderProps> = ({ onImageSelect, vis
|
||||
onCancel={handleCancel}
|
||||
footer={null}
|
||||
width={600}
|
||||
centered>
|
||||
centered
|
||||
>
|
||||
<Tabs defaultActiveKey="upload" items={tabItems} size="large" />
|
||||
</Modal>
|
||||
)
|
||||
|
||||
@ -73,7 +73,8 @@ export const TableActionMenu: FC<TableActionMenuProps> = ({ show, position, acti
|
||||
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
|
||||
minWidth: '160px',
|
||||
padding: '4px 0'
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{actions.map((action, index) => (
|
||||
<button
|
||||
key={index}
|
||||
@ -99,7 +100,8 @@ export const TableActionMenu: FC<TableActionMenuProps> = ({ show, position, acti
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.backgroundColor = 'transparent'
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{action.icon && <span>{action.icon}</span>}
|
||||
<span>{action.label}</span>
|
||||
</button>
|
||||
|
||||
@ -421,13 +421,15 @@ const YamlFrontMatterNodeView: React.FC<NodeViewProps> = ({ node, updateAttribut
|
||||
if (e.target === e.currentTarget) {
|
||||
e.preventDefault()
|
||||
}
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<PropertiesContainer
|
||||
hasContent={hasContent}
|
||||
onClick={(e) => {
|
||||
// Prevent node selection when clicking inside properties
|
||||
e.stopPropagation()
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{parsedProperties.map((property) => (
|
||||
<Dropdown
|
||||
key={property.key}
|
||||
@ -437,11 +439,13 @@ const YamlFrontMatterNodeView: React.FC<NodeViewProps> = ({ node, updateAttribut
|
||||
open={openDropdown === `context-${property.key}`}
|
||||
onOpenChange={(open) => {
|
||||
setOpenDropdown(open ? `context-${property.key}` : null)
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<PropertyRow
|
||||
onContextMenu={(e) => {
|
||||
e.stopPropagation()
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<PropertyIcon>{getPropertyIcon(property.type)}</PropertyIcon>
|
||||
<PropertyName>{property.key}</PropertyName>
|
||||
{renderPropertyValue(property)}
|
||||
@ -453,7 +457,8 @@ const YamlFrontMatterNodeView: React.FC<NodeViewProps> = ({ node, updateAttribut
|
||||
open={openDropdown === `action-${property.key}`}
|
||||
onOpenChange={(open) => {
|
||||
setOpenDropdown(open ? `action-${property.key}` : null)
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<ActionButton onClick={(e) => e.stopPropagation()} title={t('richEditor.frontMatter.moreActions')}>
|
||||
<MoreHorizontal size={14} />
|
||||
</ActionButton>
|
||||
|
||||
@ -167,7 +167,8 @@ const DragContextMenu: React.FC<DragContextMenuProps> = ({
|
||||
$danger={action.danger}
|
||||
onClick={() => handleMenuItemClick(action)}
|
||||
disabled={!action.isEnabled(editor, node, position)}
|
||||
title={action.shortcut ? `${action.label} (${action.shortcut})` : action.label}>
|
||||
title={action.shortcut ? `${action.label} (${action.shortcut})` : action.label}
|
||||
>
|
||||
{action.icon && <MenuItemIcon>{action.icon}</MenuItemIcon>}
|
||||
<MenuItemLabel>{action.label}</MenuItemLabel>
|
||||
{action.shortcut && <MenuItemShortcut>{action.shortcut}</MenuItemShortcut>}
|
||||
@ -193,7 +194,8 @@ const DragContextMenu: React.FC<DragContextMenuProps> = ({
|
||||
top: menuPosition.y
|
||||
}}
|
||||
onKeyDown={handleKeyDown}
|
||||
tabIndex={-1}>
|
||||
tabIndex={-1}
|
||||
>
|
||||
<EmptyState>No actions available for this block</EmptyState>
|
||||
</MenuContainer>
|
||||
)
|
||||
@ -212,7 +214,8 @@ const DragContextMenu: React.FC<DragContextMenuProps> = ({
|
||||
}}
|
||||
onKeyDown={handleKeyDown}
|
||||
tabIndex={-1}
|
||||
data-testid="drag-context-menu">
|
||||
data-testid="drag-context-menu"
|
||||
>
|
||||
{GROUP_ORDER.map((group, index) => {
|
||||
const actions = finalActionsByGroup[group]
|
||||
const groupElement = renderMenuGroup(group, actions)
|
||||
|
||||
@ -52,7 +52,8 @@ const PlaceholderBlock: React.FC<PlaceholderBlockProps> = ({ icon, message, onCl
|
||||
const target = e.currentTarget as HTMLElement
|
||||
target.style.borderColor = colors.border
|
||||
target.style.backgroundColor = colors.background
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{icon}
|
||||
<span style={{ color: '#656d76', fontSize: 14 }}>{message}</span>
|
||||
</div>
|
||||
|
||||
@ -390,7 +390,8 @@ const RichEditor = ({
|
||||
$isFullWidth={isFullWidth}
|
||||
$fontFamily={fontFamily}
|
||||
$fontSize={fontSize}
|
||||
onKeyDown={onKeyDownEditor}>
|
||||
onKeyDown={onKeyDownEditor}
|
||||
>
|
||||
{showToolbar && (
|
||||
<Toolbar
|
||||
editor={editor}
|
||||
|
||||
@ -170,7 +170,8 @@ export const Toolbar: React.FC<ToolbarProps> = ({ editor, formattingState, onCom
|
||||
data-active={isActive}
|
||||
disabled={isDisabled}
|
||||
onClick={() => handleCommand(command)}
|
||||
data-testid={`toolbar-${command}`}>
|
||||
data-testid={`toolbar-${command}`}
|
||||
>
|
||||
<Icon color={isActive ? 'var(--color-primary)' : 'var(--color-text)'} />
|
||||
</ToolbarButton>
|
||||
)
|
||||
|
||||
@ -238,7 +238,8 @@ export function S3BackupManager({ visible, onClose, s3Config, restoreMethod }: S
|
||||
type="link"
|
||||
danger
|
||||
onClick={() => handleDeleteSingle(record.fileName)}
|
||||
disabled={deleting || restoring}>
|
||||
disabled={deleting || restoring}
|
||||
>
|
||||
{t('settings.data.s3.manager.delete.label')}
|
||||
</Button>
|
||||
</>
|
||||
@ -271,13 +272,15 @@ export function S3BackupManager({ visible, onClose, s3Config, restoreMethod }: S
|
||||
icon={<DeleteOutlined />}
|
||||
onClick={handleDeleteSelected}
|
||||
disabled={selectedRowKeys.length === 0 || deleting}
|
||||
loading={deleting}>
|
||||
loading={deleting}
|
||||
>
|
||||
{t('settings.data.s3.manager.delete.selected', { count: selectedRowKeys.length })}
|
||||
</Button>,
|
||||
<Button key="close" onClick={onClose}>
|
||||
{t('settings.data.s3.manager.close')}
|
||||
</Button>
|
||||
]}>
|
||||
]}
|
||||
>
|
||||
<Table
|
||||
rowKey="fileName"
|
||||
columns={columns}
|
||||
|
||||
@ -78,7 +78,8 @@ export function S3BackupModal({
|
||||
onCancel={handleCancel}
|
||||
okButtonProps={{ loading: backuping }}
|
||||
transitionName="animation-move-down"
|
||||
centered>
|
||||
centered
|
||||
>
|
||||
<Input
|
||||
value={customFileName}
|
||||
onChange={(e) => setCustomFileName(e.target.value)}
|
||||
@ -222,7 +223,8 @@ export function S3RestoreModal({
|
||||
okButtonProps={{ loading: restoring }}
|
||||
width={600}
|
||||
transitionName="animation-move-down"
|
||||
centered>
|
||||
centered
|
||||
>
|
||||
<div style={{ position: 'relative' }}>
|
||||
<Select
|
||||
style={{ width: '100%' }}
|
||||
|
||||
@ -52,7 +52,8 @@ const Scrollbar: FC<ScrollbarProps> = ({ ref: passedRef, children, onScroll: ext
|
||||
{...htmlProps} // Pass other HTML attributes
|
||||
$isScrolling={isScrolling}
|
||||
onScroll={combinedOnScroll} // Use the combined handler
|
||||
ref={passedRef}>
|
||||
ref={passedRef}
|
||||
>
|
||||
{children}
|
||||
</ScrollBarContainer>
|
||||
)
|
||||
|
||||
@ -134,7 +134,8 @@ const Selector = <V extends string | number>({
|
||||
trigger={['click']}
|
||||
placement={placement}
|
||||
open={open && !disabled}
|
||||
onOpenChange={handleOpenChange}>
|
||||
onOpenChange={handleOpenChange}
|
||||
>
|
||||
<Label $size={size} $open={open} $disabled={disabled} $isPlaceholder={label === placeholder}>
|
||||
{label}
|
||||
<LabelIcon size={size + 3} />
|
||||
|
||||
@ -27,7 +27,8 @@ export default function Spinner({ text }: Props) {
|
||||
repeat: Infinity,
|
||||
repeatType: 'reverse',
|
||||
ease: 'easeInOut'
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<Search size={16} style={{ color: 'unset' }} />
|
||||
<span>{text}</span>
|
||||
</Searching>
|
||||
|
||||
@ -206,7 +206,8 @@ const TabsContainer: React.FC<TabsContainerProps> = ({ children }) => {
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
closeTab(tab.id)
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<X size={12} />
|
||||
</CloseButton>
|
||||
)}
|
||||
@ -221,7 +222,8 @@ const TabsContainer: React.FC<TabsContainerProps> = ({ children }) => {
|
||||
<Tooltip
|
||||
title={t('settings.theme.title') + ': ' + getThemeModeLabel(settedTheme)}
|
||||
mouseEnterDelay={0.8}
|
||||
placement="bottom">
|
||||
placement="bottom"
|
||||
>
|
||||
<ThemeButton onClick={toggleTheme}>
|
||||
{settedTheme === ThemeMode.dark ? (
|
||||
<Moon size={16} />
|
||||
|
||||
@ -42,7 +42,8 @@ const CustomTag: FC<CustomTagProps> = ({
|
||||
style={{
|
||||
...(disabled && { cursor: 'not-allowed' }),
|
||||
...style
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{icon && icon} {children}
|
||||
{closable && (
|
||||
<CloseIcon
|
||||
|
||||
@ -16,7 +16,8 @@ export const ReasoningTag = ({ size, showTooltip, showLabel, ...restProps }: Pro
|
||||
color="#6372bd"
|
||||
icon={<i className="iconfont icon-thinking" />}
|
||||
tooltip={showTooltip ? t('models.type.reasoning') : undefined}
|
||||
{...restProps}>
|
||||
{...restProps}
|
||||
>
|
||||
{showLabel ? t('models.type.reasoning') : ''}
|
||||
</CustomTag>
|
||||
)
|
||||
|
||||
@ -17,7 +17,8 @@ export const ToolsCallingTag = ({ size, showTooltip, showLabel, ...restProps }:
|
||||
color="#f18737"
|
||||
icon={<ToolOutlined style={{ fontSize: size }} />}
|
||||
tooltip={showTooltip ? t('models.type.function_calling') : undefined}
|
||||
{...restProps}>
|
||||
{...restProps}
|
||||
>
|
||||
{showLabel ? t('models.type.function_calling') : ''}
|
||||
</CustomTag>
|
||||
)
|
||||
|
||||
@ -18,7 +18,8 @@ export const VisionTag = ({ size, showTooltip, showLabel, ...restProps }: Props)
|
||||
color="#00b96b"
|
||||
icon={<EyeOutlined style={{ fontSize: size }} />}
|
||||
tooltip={showTooltip ? t('models.type.vision') : undefined}
|
||||
{...restProps}>
|
||||
{...restProps}
|
||||
>
|
||||
{showLabel ? t('models.type.vision') : ''}
|
||||
</CustomTag>
|
||||
)
|
||||
|
||||
@ -18,7 +18,8 @@ export const WebSearchTag = ({ size, showTooltip, showLabel, ...restProps }: Pro
|
||||
color="#1677ff"
|
||||
icon={<GlobalOutlined style={{ fontSize: size }} />}
|
||||
tooltip={showTooltip ? t('models.type.websearch') : undefined}
|
||||
{...restProps}>
|
||||
{...restProps}
|
||||
>
|
||||
{showLabel ? t('models.type.websearch') : ''}
|
||||
</CustomTag>
|
||||
)
|
||||
|
||||
@ -11,7 +11,8 @@ export const WarnTag = ({ iconSize: size = 14, message }: Props) => {
|
||||
return (
|
||||
<CustomTag
|
||||
icon={<AlertTriangleIcon size={size} color="var(--color-status-warning)" />}
|
||||
color="var(--color-status-warning)">
|
||||
color="var(--color-status-warning)"
|
||||
>
|
||||
{message}
|
||||
</CustomTag>
|
||||
)
|
||||
|
||||
@ -65,7 +65,8 @@ const ThinkingEffect: React.FC<Props> = ({ isThinking, thinkingTimeText, content
|
||||
transition={{
|
||||
duration: 0.15,
|
||||
ease: 'linear'
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{messages.map((message, index) => {
|
||||
if (index < messages.length - 5) return null
|
||||
|
||||
|
||||
@ -67,7 +67,8 @@ const TranslateButton: FC<Props> = ({ text, onTranslated, disabled, style, isLoa
|
||||
placement="top"
|
||||
title={t('chat.input.translate', { target_language: getLanguageByLangcode(targetLanguage).label() })}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
arrow
|
||||
>
|
||||
<ToolbarButton onClick={handleTranslate} disabled={disabled || isTranslating} style={style} type="text">
|
||||
{isTranslating ? <LoadingOutlined spin /> : <Languages size={18} />}
|
||||
</ToolbarButton>
|
||||
|
||||
@ -199,13 +199,15 @@ function DynamicVirtualList<T>(props: DynamicVirtualListProps<T>) {
|
||||
overflow: 'auto',
|
||||
...(horizontal ? { width: size ?? '100%' } : { height: size ?? '100%' }),
|
||||
...scrollerStyle
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
position: 'relative',
|
||||
width: horizontal ? `${totalSize}px` : '100%',
|
||||
height: !horizontal ? `${totalSize}px` : '100%'
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{virtualItems.map((virtualItem) => {
|
||||
const isItemSticky = stickyIndexes.includes(virtualItem.index)
|
||||
const isItemActiveSticky = isItemSticky && activeStickyIndexRef.current === virtualItem.index
|
||||
|
||||
@ -245,7 +245,8 @@ export function WebdavBackupManager({
|
||||
type="link"
|
||||
danger
|
||||
onClick={() => handleDeleteSingle(record.fileName)}
|
||||
disabled={deleting || restoring}>
|
||||
disabled={deleting || restoring}
|
||||
>
|
||||
{t('settings.data.webdav.backup.manager.delete.text')}
|
||||
</Button>
|
||||
</>
|
||||
@ -278,13 +279,15 @@ export function WebdavBackupManager({
|
||||
icon={<DeleteOutlined />}
|
||||
onClick={handleDeleteSelected}
|
||||
disabled={selectedRowKeys.length === 0 || deleting}
|
||||
loading={deleting}>
|
||||
loading={deleting}
|
||||
>
|
||||
{t('settings.data.webdav.backup.manager.delete.selected')} ({selectedRowKeys.length})
|
||||
</Button>,
|
||||
<Button key="close" onClick={onClose}>
|
||||
{t('common.close')}
|
||||
</Button>
|
||||
]}>
|
||||
]}
|
||||
>
|
||||
<Table
|
||||
rowKey="fileName"
|
||||
columns={columns}
|
||||
|
||||
@ -76,7 +76,8 @@ export function WebdavBackupModal({
|
||||
onCancel={handleCancel}
|
||||
okButtonProps={{ loading: backuping }}
|
||||
transitionName="animation-move-down"
|
||||
centered>
|
||||
centered
|
||||
>
|
||||
<Input
|
||||
value={customFileName}
|
||||
onChange={(e) => setCustomFileName(e.target.value)}
|
||||
|
||||
@ -25,7 +25,8 @@ export const WindowRestoreIcon = ({ size = '1.1em', ...props }: WindowRestoreIco
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}>
|
||||
{...props}
|
||||
>
|
||||
<defs id="defs1" />
|
||||
<rect
|
||||
width="14.165795"
|
||||
@ -93,7 +94,8 @@ const WindowControls: React.FC = () => {
|
||||
<Tooltip
|
||||
title={isMaximized ? t('navbar.window.restore') : t('navbar.window.maximize')}
|
||||
placement="bottom"
|
||||
mouseEnterDelay={DEFAULT_DELAY}>
|
||||
mouseEnterDelay={DEFAULT_DELAY}
|
||||
>
|
||||
<ControlButton onClick={handleMaximize} aria-label={isMaximized ? 'Restore' : 'Maximize'}>
|
||||
{isMaximized ? <WindowRestoreIcon size={14} /> : <Square size={14} />}
|
||||
</ControlButton>
|
||||
|
||||
@ -90,7 +90,8 @@ export const SidebarOpenedMinappTabs: FC = () => {
|
||||
<Icon
|
||||
theme={theme}
|
||||
onClick={() => handleOnClick(app)}
|
||||
className={`${isActive ? 'opened-active' : ''}`}>
|
||||
className={`${isActive ? 'opened-active' : ''}`}
|
||||
>
|
||||
<MinAppIcon size={20} app={app} style={{ borderRadius: 6 }} sidebar />
|
||||
</Icon>
|
||||
</Dropdown>
|
||||
@ -131,7 +132,8 @@ export const SidebarPinnedApps: FC = () => {
|
||||
<Icon
|
||||
theme={theme}
|
||||
onClick={() => openMinappKeepAlive(app)}
|
||||
className={`${isActive ? 'active' : ''} ${openedKeepAliveMinapps.some((item) => item.id === app.id) ? 'opened-minapp' : ''}`}>
|
||||
className={`${isActive ? 'active' : ''} ${openedKeepAliveMinapps.some((item) => item.id === app.id) ? 'opened-minapp' : ''}`}
|
||||
>
|
||||
<MinAppIcon size={20} app={app} style={{ borderRadius: 6 }} sidebar />
|
||||
</Icon>
|
||||
</Dropdown>
|
||||
|
||||
@ -66,7 +66,8 @@ const Sidebar: FC = () => {
|
||||
<Container
|
||||
$isFullscreen={isFullscreen}
|
||||
id="app-sidebar"
|
||||
style={{ backgroundColor, zIndex: minappShow ? 10000 : 'initial' }}>
|
||||
style={{ backgroundColor, zIndex: minappShow ? 10000 : 'initial' }}
|
||||
>
|
||||
{isEmoji(avatar) ? (
|
||||
<EmojiAvatar onClick={onEditUser} className="sidebar-avatar" size={31} fontSize={18}>
|
||||
{avatar}
|
||||
@ -92,7 +93,8 @@ const Sidebar: FC = () => {
|
||||
<Tooltip
|
||||
title={t('settings.theme.title') + ': ' + getThemeModeLabel(settedTheme)}
|
||||
mouseEnterDelay={0.8}
|
||||
placement="right">
|
||||
placement="right"
|
||||
>
|
||||
<Icon theme={theme} onClick={toggleTheme}>
|
||||
{settedTheme === ThemeMode.dark ? (
|
||||
<Moon size={20} className="icon" />
|
||||
@ -108,7 +110,8 @@ const Sidebar: FC = () => {
|
||||
onClick={async () => {
|
||||
hideMinappPopup()
|
||||
await to('/settings/provider')
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<Icon theme={theme} className={pathname.startsWith('/settings') && !minappShow ? 'active' : ''}>
|
||||
<Settings size={20} className="icon" />
|
||||
</Icon>
|
||||
@ -165,7 +168,8 @@ const MainMenus: FC = () => {
|
||||
hideMinappPopup()
|
||||
await modelGenerating()
|
||||
navigate(path)
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<Icon theme={theme} className={isActive}>
|
||||
{iconMap[icon]}
|
||||
</Icon>
|
||||
|
||||
@ -54,11 +54,13 @@ export function ItemRenderer<T>({
|
||||
ref={ref}
|
||||
data-index={index}
|
||||
className={classNames({ dragOverlay: dragOverlay })}
|
||||
style={{ ...wrapperStyle }}>
|
||||
style={{ ...wrapperStyle }}
|
||||
>
|
||||
<DraggableItem
|
||||
className={classNames({ dragging: dragging, dragOverlay: dragOverlay, ghost: ghost })}
|
||||
{...listeners}
|
||||
{...props}>
|
||||
{...props}
|
||||
>
|
||||
{renderItem(item, { dragging: !!dragging })}
|
||||
</DraggableItem>
|
||||
</ItemWrapper>
|
||||
|
||||
@ -178,14 +178,16 @@ function Sortable<T>({
|
||||
onDragStart={handleDragStart}
|
||||
onDragEnd={handleDragEnd}
|
||||
onDragCancel={handleDragCancel}
|
||||
modifiers={modifiers}>
|
||||
modifiers={modifiers}
|
||||
>
|
||||
<SortableContext items={itemIds} strategy={strategy}>
|
||||
<ListWrapper
|
||||
className={className}
|
||||
data-layout={layout}
|
||||
data-direction={horizontal ? 'horizontal' : 'vertical'}
|
||||
$gap={gap}
|
||||
style={listStyle}>
|
||||
style={listStyle}
|
||||
>
|
||||
{items.map((item, index) => (
|
||||
<SortableItem
|
||||
key={itemIds[index]}
|
||||
|
||||
@ -112,7 +112,8 @@ const AntdProvider: FC<PropsWithChildren> = ({ children }) => {
|
||||
colorBgMask: _theme === 'dark' ? 'rgba(0,0,0,0.7)' : 'rgba(255,255,255,0.8)',
|
||||
motionDurationMid: '100ms'
|
||||
}
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</ConfigProvider>
|
||||
)
|
||||
|
||||
@ -16,7 +16,8 @@ const StyleSheetManager = ({ children }: StyleSheetManagerProps): React.ReactEle
|
||||
}
|
||||
// 对于自定义组件,允许所有非特殊属性通过
|
||||
return prop !== '$' && !prop.startsWith('$')
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</StyledComponentsStyleSheetManager>
|
||||
)
|
||||
|
||||
@ -220,7 +220,8 @@ const AgentsPage: FC = () => {
|
||||
</Flex>
|
||||
}
|
||||
style={{ margin: '0 8px', paddingLeft: 16, paddingRight: 16 }}
|
||||
onClick={handleGroupClick(group)}></ListItem>
|
||||
onClick={handleGroupClick(group)}
|
||||
></ListItem>
|
||||
))}
|
||||
</AgentsGroupList>
|
||||
|
||||
@ -268,7 +269,8 @@ const AgentsPage: FC = () => {
|
||||
<Button
|
||||
type="text"
|
||||
onClick={handleSearchIconClick}
|
||||
icon={<Search size={18} color="var(--color-icon)" />}>
|
||||
icon={<Search size={18} color="var(--color-icon)" />}
|
||||
>
|
||||
{t('common.search')}
|
||||
</Button>
|
||||
)
|
||||
|
||||
@ -170,7 +170,8 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
okText={t('agents.add.title')}
|
||||
width={600}
|
||||
transitionName="animation-move-down"
|
||||
centered>
|
||||
centered
|
||||
>
|
||||
<Form
|
||||
ref={formRef}
|
||||
form={form}
|
||||
@ -188,7 +189,8 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
|
||||
const currentValues = form.getFieldsValue()
|
||||
setHasUnsavedChanges(currentValues.name?.trim() || currentValues.prompt?.trim() || emoji)
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<Form.Item name="name" label="Emoji">
|
||||
<Popover
|
||||
content={
|
||||
@ -200,7 +202,8 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
/>
|
||||
}
|
||||
arrow
|
||||
trigger="click">
|
||||
trigger="click"
|
||||
>
|
||||
<Button icon={emoji && <span style={{ fontSize: 20 }}>{emoji}</span>}>{t('common.select')}</Button>
|
||||
</Popover>
|
||||
</Form.Item>
|
||||
@ -212,7 +215,8 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
name="prompt"
|
||||
label={t('agents.add.prompt.label')}
|
||||
rules={[{ required: true }]}
|
||||
style={{ position: 'relative' }}>
|
||||
style={{ position: 'relative' }}
|
||||
>
|
||||
<TextArea placeholder={t('agents.add.prompt.placeholder')} spellCheck={false} rows={10} />
|
||||
</Form.Item>
|
||||
<TokenCount>Tokens: {tokenCount}</TokenCount>
|
||||
@ -234,7 +238,8 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
<Form.Item
|
||||
name="knowledge_base_ids"
|
||||
label={t('agents.add.knowledge_base.label')}
|
||||
rules={[{ required: false }]}>
|
||||
rules={[{ required: false }]}
|
||||
>
|
||||
<Select
|
||||
mode="multiple"
|
||||
allowClear
|
||||
|
||||
@ -158,7 +158,8 @@ const AgentCard: FC<Props> = ({ agent, onClick, activegroup, getLocalizedGroupNa
|
||||
items: menuItems
|
||||
}}
|
||||
trigger={['click']}
|
||||
placement="bottomRight">
|
||||
placement="bottomRight"
|
||||
>
|
||||
<MenuButton
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
@ -189,7 +190,8 @@ const AgentCard: FC<Props> = ({ agent, onClick, activegroup, getLocalizedGroupNa
|
||||
menu={{
|
||||
items: menuItems
|
||||
}}
|
||||
trigger={['contextMenu']}>
|
||||
trigger={['contextMenu']}
|
||||
>
|
||||
{content}
|
||||
</Dropdown>
|
||||
)
|
||||
|
||||
@ -106,7 +106,8 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
</Flex>
|
||||
}
|
||||
transitionName="animation-move-down"
|
||||
centered>
|
||||
centered
|
||||
>
|
||||
<Form form={form} onFinish={onFinish} layout="vertical">
|
||||
<Form.Item>
|
||||
<Radio.Group value={importType} onChange={(e) => setImportType(e.target.value)}>
|
||||
|
||||
@ -40,7 +40,8 @@ const PopupContainer: React.FC = () => {
|
||||
afterClose={onClose}
|
||||
footer={null}
|
||||
transitionName="animation-move-down"
|
||||
centered>
|
||||
centered
|
||||
>
|
||||
<Container>
|
||||
{agents.length > 0 && (
|
||||
<DraggableList list={agents} onUpdate={updateAgents}>
|
||||
|
||||
@ -235,7 +235,8 @@ const CodeToolsPage: FC = () => {
|
||||
icon={<Download size={14} />}
|
||||
onClick={handleInstallBun}
|
||||
loading={isInstallingBun}
|
||||
disabled={isInstallingBun}>
|
||||
disabled={isInstallingBun}
|
||||
>
|
||||
{isInstallingBun ? t('code.installing_bun') : t('code.install_bun')}
|
||||
</Button>
|
||||
</div>
|
||||
@ -270,7 +271,8 @@ const CodeToolsPage: FC = () => {
|
||||
<Link
|
||||
key={provider.id}
|
||||
style={{ color: 'var(--color-text)', display: 'flex', alignItems: 'center', gap: 4 }}
|
||||
to={`/settings/provider?id=${provider.id}`}>
|
||||
to={`/settings/provider?id=${provider.id}`}
|
||||
>
|
||||
<ProviderLogo shape="square" src={getProviderLogo(provider.id)} size={20} />
|
||||
{getProviderLabel(provider.id)}
|
||||
<ArrowUpRight size={14} />
|
||||
@ -281,7 +283,8 @@ const CodeToolsPage: FC = () => {
|
||||
</div>
|
||||
}
|
||||
trigger="hover"
|
||||
placement="right">
|
||||
placement="right"
|
||||
>
|
||||
<HelpCircle size={14} style={{ color: 'var(--color-text-3)', cursor: 'pointer' }} />
|
||||
</Popover>
|
||||
)}
|
||||
@ -358,7 +361,8 @@ const CodeToolsPage: FC = () => {
|
||||
onClick={handleLaunch}
|
||||
loading={isLaunching}
|
||||
disabled={!canLaunch || !isBunInstalled}
|
||||
block>
|
||||
block
|
||||
>
|
||||
{isLaunching ? t('code.launching') : t('code.launch.label')}
|
||||
</Button>
|
||||
</MainContent>
|
||||
|
||||
@ -68,7 +68,8 @@ const FileList: React.FC<FileItemProps> = ({ id, list, files }) => {
|
||||
},
|
||||
icon: <ExclamationCircleOutlined style={{ color: 'red' }} />
|
||||
})
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<DeleteIcon size={14} className="lucide-custom" />
|
||||
</DeleteButton>
|
||||
</ImageWrapper>
|
||||
@ -91,7 +92,8 @@ const FileList: React.FC<FileItemProps> = ({ id, list, files }) => {
|
||||
itemContainerStyle={{
|
||||
height: '75px',
|
||||
paddingTop: '12px'
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{(item) => (
|
||||
<FileItem
|
||||
key={item.key}
|
||||
|
||||
@ -119,7 +119,8 @@ const FilesPage: FC = () => {
|
||||
cancelText={t('common.cancel')}
|
||||
onConfirm={() => handleDelete(file.id, t)}
|
||||
placement="left"
|
||||
icon={<ExclamationCircleOutlined style={{ color: 'red' }} />}>
|
||||
icon={<ExclamationCircleOutlined style={{ color: 'red' }} />}
|
||||
>
|
||||
<Button type="text" danger icon={<DeleteIcon size={14} className="lucide-custom" />} />
|
||||
</Popconfirm>
|
||||
{fileType !== 'image' && (
|
||||
@ -172,7 +173,8 @@ const FilesPage: FC = () => {
|
||||
setSortField(field as 'created_at' | 'size' | 'name')
|
||||
setSortOrder('desc')
|
||||
}
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{getFileFieldLabel(field)}
|
||||
{sortField === field &&
|
||||
(sortOrder === 'desc' ? <ArrowUpWideNarrow size={12} /> : <ArrowDownNarrowWide size={12} />)}
|
||||
@ -196,18 +198,21 @@ const FilesPage: FC = () => {
|
||||
okText={t('common.confirm')}
|
||||
cancelText={t('common.cancel')}
|
||||
onConfirm={handleBatchDelete}
|
||||
icon={<ExclamationCircleOutlined style={{ color: 'red' }} />}>
|
||||
icon={<ExclamationCircleOutlined style={{ color: 'red' }} />}
|
||||
>
|
||||
{t('files.batch_delete')} ({selectedFileIds.length})
|
||||
</Popconfirm>
|
||||
)
|
||||
}
|
||||
]
|
||||
}}
|
||||
trigger={['click']}>
|
||||
trigger={['click']}
|
||||
>
|
||||
<Checkbox
|
||||
indeterminate={selectedFileIds.length > 0 && selectedFileIds.length < sortedFiles.length}
|
||||
checked={selectedFileIds.length === sortedFiles.length && sortedFiles.length > 0}
|
||||
onChange={(e) => handleSelectAll(e.target.checked)}>
|
||||
onChange={(e) => handleSelectAll(e.target.checked)}
|
||||
>
|
||||
{t('files.batch_operation')}
|
||||
</Checkbox>
|
||||
</Dropdown.Button>
|
||||
|
||||
@ -154,7 +154,8 @@ const SearchResults: FC<Props> = ({ keywords, onMessageClick, onTopicClick, ...p
|
||||
<Title
|
||||
level={5}
|
||||
style={{ color: 'var(--color-primary)', cursor: 'pointer' }}
|
||||
onClick={() => onTopicClick(topic)}>
|
||||
onClick={() => onTopicClick(topic)}
|
||||
>
|
||||
{topic.name}
|
||||
</Title>
|
||||
<div style={{ cursor: 'pointer' }} onClick={() => onMessageClick(message)}>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user