Skip to content

Commit 37296be

Browse files
RockChinQclaude
andcommitted
feat: refactor plugin market interaction and migrate to LangBot Space
- Replace plugin detail dialog with hover buttons interaction - Add "Install" and "View Details" hover buttons on plugin cards - Remove PluginDetailDialog component - Update plugin marketplace URL format to /market/{author}/{plugin} - Redirect all plugin detail views to LangBot Space - Add i18n support for 4 languages (zh-Hans, en-US, zh-Hant, ja-JP) - Optimize hover overlay styles for light/dark theme 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 6c03a1d commit 37296be

File tree

8 files changed

+82
-463
lines changed

8 files changed

+82
-463
lines changed

web/src/app/home/plugins/components/plugin-market/PluginMarketComponent.tsx

Lines changed: 31 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group';
1414
import { Search, Loader2, Wrench, AudioWaveform, Hash } from 'lucide-react';
1515
import PluginMarketCardComponent from './plugin-market-card/PluginMarketCardComponent';
1616
import { PluginMarketCardVO } from './plugin-market-card/PluginMarketCardVO';
17-
import PluginDetailDialog from './plugin-detail-dialog/PluginDetailDialog';
1817
import { getCloudServiceClientSync } from '@/app/infra/http';
1918
import { useTranslation } from 'react-i18next';
2019
import { PluginV4 } from '@/app/infra/entities/plugin';
@@ -48,15 +47,6 @@ function MarketPageContent({
4847
const [total, setTotal] = useState(0);
4948
const [sortOption, setSortOption] = useState('install_count_desc');
5049

51-
// Plugin detail dialog state
52-
const [selectedPluginAuthor, setSelectedPluginAuthor] = useState<
53-
string | null
54-
>(null);
55-
const [selectedPluginName, setSelectedPluginName] = useState<string | null>(
56-
null,
57-
);
58-
const [dialogOpen, setDialogOpen] = useState(false);
59-
6050
const pageSize = 16; // 每页16个,4行x4列
6151
const searchTimeoutRef = useRef<NodeJS.Timeout | null>(null);
6252
const scrollContainerRef = useRef<HTMLDivElement | null>(null);
@@ -230,34 +220,47 @@ function MarketPageContent({
230220
fetchPlugins(1, !!searchQuery.trim(), true);
231221
}, [sortOption, componentFilter]);
232222

233-
// 处理URL参数,检查是否需要打开插件详情对话框
223+
// 处理URL参数,重定向到 LangBot Space
234224
useEffect(() => {
235225
const author = searchParams.get('author');
236226
const pluginName = searchParams.get('plugin');
237227

238228
if (author && pluginName) {
239-
setSelectedPluginAuthor(author);
240-
setSelectedPluginName(pluginName);
241-
setDialogOpen(true);
229+
const detailUrl = `https://space.langbot.app/market/${author}/${pluginName}`;
230+
window.open(detailUrl, '_blank');
242231
}
243232
}, [searchParams]);
244233

245-
// 插件详情对话框处理函数
246-
const handlePluginClick = useCallback(
247-
(author: string, pluginName: string) => {
248-
setSelectedPluginAuthor(author);
249-
setSelectedPluginName(pluginName);
250-
setDialogOpen(true);
234+
// 处理安装插件
235+
const handleInstallPlugin = useCallback(
236+
async (author: string, pluginName: string) => {
237+
try {
238+
// Find the full plugin object from the list
239+
const pluginVO = plugins.find(
240+
(p) => p.author === author && p.pluginName === pluginName,
241+
);
242+
if (!pluginVO) {
243+
console.error('Plugin not found:', author, pluginName);
244+
return;
245+
}
246+
247+
// Fetch full plugin details to get PluginV4 object
248+
const response = await getCloudServiceClientSync().getPluginDetail(
249+
author,
250+
pluginName,
251+
);
252+
const pluginV4: PluginV4 = response.plugin;
253+
254+
// Call the install function passed from parent
255+
installPlugin(pluginV4);
256+
} catch (error) {
257+
console.error('Failed to install plugin:', error);
258+
toast.error(t('market.installFailed'));
259+
}
251260
},
252-
[],
261+
[plugins, installPlugin, t],
253262
);
254263

255-
const handleDialogClose = useCallback(() => {
256-
setDialogOpen(false);
257-
setSelectedPluginAuthor(null);
258-
setSelectedPluginName(null);
259-
}, []);
260-
261264
// 清理定时器
262265
useEffect(() => {
263266
return () => {
@@ -459,7 +462,7 @@ function MarketPageContent({
459462
<PluginMarketCardComponent
460463
key={plugin.pluginId}
461464
cardVO={plugin}
462-
onPluginClick={handlePluginClick}
465+
onInstall={handleInstallPlugin}
463466
/>
464467
))}
465468
</div>
@@ -490,15 +493,6 @@ function MarketPageContent({
490493
</>
491494
)}
492495
</div>
493-
494-
{/* Plugin detail dialog */}
495-
<PluginDetailDialog
496-
open={dialogOpen}
497-
onOpenChange={handleDialogClose}
498-
author={selectedPluginAuthor}
499-
pluginName={selectedPluginName}
500-
installPlugin={installPlugin}
501-
/>
502496
</div>
503497
);
504498
}

0 commit comments

Comments
 (0)