Compare commits

...

3 Commits

Author SHA1 Message Date
Junyan Qin
763c1a885c perf: url display in webhook dialog 2025-11-20 16:48:06 +08:00
Junyan Qin
dbc09f46f4 perf: provider icon rounded in hovercard 2025-11-20 10:25:29 +08:00
Junyan Qin
cf43f09aff perf: auto refresh logic in market 2025-11-20 10:18:28 +08:00
4 changed files with 67 additions and 18 deletions

View File

@@ -289,12 +289,16 @@ export default function ApiIntegrationDialog({
{t('common.noApiKeys')}
</div>
) : (
<div className="border rounded-md">
<div className="border rounded-md overflow-x-auto">
<Table>
<TableHeader>
<TableRow>
<TableHead>{t('common.name')}</TableHead>
<TableHead>{t('common.apiKeyValue')}</TableHead>
<TableHead className="min-w-[120px]">
{t('common.name')}
</TableHead>
<TableHead className="min-w-[200px]">
{t('common.apiKeyValue')}
</TableHead>
<TableHead className="w-[100px]">
{t('common.actions')}
</TableHead>
@@ -372,16 +376,20 @@ export default function ApiIntegrationDialog({
{t('common.noWebhooks')}
</div>
) : (
<div className="border rounded-md">
<Table>
<div className="border rounded-md overflow-x-auto max-w-full">
<Table className="table-fixed w-full">
<TableHeader>
<TableRow>
<TableHead>{t('common.name')}</TableHead>
<TableHead>{t('common.webhookUrl')}</TableHead>
<TableHead className="w-[150px]">
{t('common.name')}
</TableHead>
<TableHead className="w-[380px]">
{t('common.webhookUrl')}
</TableHead>
<TableHead className="w-[80px]">
{t('common.webhookEnabled')}
</TableHead>
<TableHead className="w-[100px]">
<TableHead className="w-[80px]">
{t('common.actions')}
</TableHead>
</TableRow>
@@ -389,20 +397,30 @@ export default function ApiIntegrationDialog({
<TableBody>
{webhooks.map((webhook) => (
<TableRow key={webhook.id}>
<TableCell>
<div>
<div className="font-medium">{webhook.name}</div>
<TableCell className="truncate">
<div className="truncate">
<div
className="font-medium truncate"
title={webhook.name}
>
{webhook.name}
</div>
{webhook.description && (
<div className="text-sm text-muted-foreground">
<div
className="text-sm text-muted-foreground truncate"
title={webhook.description}
>
{webhook.description}
</div>
)}
</div>
</TableCell>
<TableCell>
<code className="text-sm bg-muted px-2 py-1 rounded break-all">
{webhook.url}
</code>
<div className="overflow-x-auto max-w-[380px]">
<code className="text-sm bg-muted px-2 py-1 rounded whitespace-nowrap inline-block">
{webhook.url}
</code>
</div>
</TableCell>
<TableCell>
<Switch

View File

@@ -240,7 +240,7 @@ export default function DynamicFormItemComponent({
model.requester,
)}
alt="icon"
className="w-8 h-8 rounded-full"
className="w-8 h-8 rounded-[8%]"
/>
<h4 className="font-medium">{model.name}</h4>
</div>

View File

@@ -235,7 +235,7 @@ export default function KBForm({
model.requester,
)}
alt="icon"
className="w-8 h-8 rounded-full"
className="w-8 h-8 rounded-[8%]"
/>
<h4 className="font-medium">
{model.name}

View File

@@ -263,6 +263,18 @@ function MarketPageContent({
}
}, [currentPage, isLoadingMore, hasMore, fetchPlugins, searchQuery]);
// Check if content fills the viewport and load more if needed
const checkAndLoadMore = useCallback(() => {
const scrollContainer = scrollContainerRef.current;
if (!scrollContainer || isLoading || isLoadingMore || !hasMore) return;
const { scrollHeight, clientHeight } = scrollContainer;
// If content doesn't fill the viewport (no scrollbar), load more
if (scrollHeight <= clientHeight) {
loadMore();
}
}, [loadMore, isLoading, isLoadingMore, hasMore]);
// Listen to scroll events on the scroll container
useEffect(() => {
const scrollContainer = scrollContainerRef.current;
@@ -280,6 +292,25 @@ function MarketPageContent({
return () => scrollContainer.removeEventListener('scroll', handleScroll);
}, [loadMore]);
// Check if we need to load more after content changes or initial load
useEffect(() => {
// Small delay to ensure DOM has updated
const timer = setTimeout(() => {
checkAndLoadMore();
}, 100);
return () => clearTimeout(timer);
}, [plugins, checkAndLoadMore]);
// Also check on window resize
useEffect(() => {
const handleResize = () => {
checkAndLoadMore();
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, [checkAndLoadMore]);
// 安装插件
// const handleInstallPlugin = (plugin: PluginV4) => {
// console.log('install plugin', plugin);
@@ -360,7 +391,7 @@ function MarketPageContent({
</div>
) : (
<>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 gap-6 pb-6">
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 gap-6 pb-6 pt-4">
{plugins.map((plugin) => (
<PluginMarketCardComponent
key={plugin.pluginId}