Files
LangBot/web/src/app/home/plugins/page.tsx
2025-05-09 16:32:54 +08:00

145 lines
5.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import PluginInstalledComponent, { PluginInstalledComponentRef } from '@/app/home/plugins/plugin-installed/PluginInstalledComponent';
import PluginMarketComponent from '@/app/home/plugins/plugin-market/PluginMarketComponent';
import styles from './plugins.module.css';
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Button } from "@/components/ui/button";
import { PlusIcon } from "lucide-react";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { GithubIcon } from "lucide-react";
import { useState, useRef, useEffect } from 'react';
import { httpClient } from '@/app/infra/http/HttpClient';
enum PluginInstallStatus {
WAIT_INPUT = 'wait_input',
INSTALLING = 'installing',
ERROR = 'error',
}
export default function PluginConfigPage() {
const [modalOpen, setModalOpen] = useState(false);
const [pluginInstallStatus, setPluginInstallStatus] = useState<PluginInstallStatus>(PluginInstallStatus.WAIT_INPUT);
const [installError, setInstallError] = useState<string | null>(null);
const [githubURL, setGithubURL] = useState('');
const pluginInstalledRef = useRef<PluginInstalledComponentRef>(null);
function handleModalConfirm() {
installPlugin(githubURL);
}
function installPlugin(url: string) {
setPluginInstallStatus(PluginInstallStatus.INSTALLING);
httpClient
.installPluginFromGithub(url)
.then((resp) => {
const taskId = resp.task_id;
// 每秒拉取一次任务状态
const interval = setInterval(() => {
httpClient.getAsyncTask(taskId).then((resp) => {
console.log('task status:', resp);
if (resp.runtime.done) {
clearInterval(interval);
if (resp.runtime.exception) {
setInstallError(resp.runtime.exception);
setPluginInstallStatus(PluginInstallStatus.ERROR);
} else { // success
setGithubURL('');
setModalOpen(false);
pluginInstalledRef.current?.refreshPluginList();
}
}
});
}, 1000);
})
.catch((err) => {
console.log('error when install plugin:', err);
setInstallError(err.message);
setPluginInstallStatus(PluginInstallStatus.ERROR);
});
}
return (
<div className={styles.pageContainer}>
<Tabs defaultValue="installed" className="w-full">
<div className='flex flex-row justify-between items-center'>
<TabsList className='shadow-md py-5 bg-[#f0f0f0]'>
<TabsTrigger value="installed" className="px-6 py-4"></TabsTrigger>
<TabsTrigger value="market" className="px-6 py-4"></TabsTrigger>
</TabsList>
<div className='flex flex-row justify-end items-center'>
<Button variant="default" className='px-6 py-4' onClick={() => {
setModalOpen(true);
setPluginInstallStatus(PluginInstallStatus.WAIT_INPUT);
setInstallError(null);
}}>
<PlusIcon className='w-4 h-4' />
</Button>
</div>
</div>
<TabsContent value="installed">
<PluginInstalledComponent ref={pluginInstalledRef} />
</TabsContent>
<TabsContent value="market">
<PluginMarketComponent askInstallPlugin={(githubURL) => {
setGithubURL(githubURL);
setModalOpen(true);
setPluginInstallStatus(PluginInstallStatus.WAIT_INPUT);
setInstallError(null);
}} />
</TabsContent>
</Tabs>
<Dialog open={modalOpen} onOpenChange={setModalOpen}>
<DialogContent className="w-[500px] p-6">
<DialogHeader>
<DialogTitle className="flex items-center gap-4">
<GithubIcon className="size-6" />
<span> GitHub </span>
</DialogTitle>
</DialogHeader>
{pluginInstallStatus === PluginInstallStatus.WAIT_INPUT && (
<div className="mt-4">
<p className="mb-2"> GitHub </p>
<Input
placeholder="请输入插件的Github链接"
value={githubURL}
onChange={(e) => setGithubURL(e.target.value)}
className="mb-4"
/>
</div>
)}
{pluginInstallStatus === PluginInstallStatus.INSTALLING && (
<div className="mt-4">
<p className="mb-2">...</p>
</div>
)}
{pluginInstallStatus === PluginInstallStatus.ERROR && (
<div className="mt-4">
<p className="mb-2"></p>
<p className="mb-2 text-red-500">{installError}</p>
</div>
)}
<DialogFooter>
{pluginInstallStatus === PluginInstallStatus.WAIT_INPUT && (
<>
<Button variant="outline" onClick={() => setModalOpen(false)}></Button>
<Button onClick={handleModalConfirm}></Button>
</>
)}
{pluginInstallStatus === PluginInstallStatus.ERROR && (
<Button variant="default" onClick={() => setModalOpen(false)}></Button>
)}
</DialogFooter>
</DialogContent>
</Dialog>
</div>
);
}