mirror of
https://github.com/lobehub/lobehub.git
synced 2026-03-27 13:29:15 +07:00
✨ feat: change the klavis Linear to LobeHub oauth Linear (#11339)
feat: change the klavis Linear to LobeHub oauth Linear
This commit is contained in:
@@ -32,5 +32,6 @@
|
||||
"login.title": "Login to {{clientName}}",
|
||||
"login.userWelcome": "Welcome back, ",
|
||||
"success.subTitle": "You have successfully authorized the application to access your account. You may now close this page.",
|
||||
"success.subTitleWithCountdown": "Authorization successful. Auto-closing in {{countdown}}s...",
|
||||
"success.title": "Authorization Successful"
|
||||
}
|
||||
|
||||
@@ -32,5 +32,6 @@
|
||||
"login.title": "登录 {{clientName}}",
|
||||
"login.userWelcome": "欢迎回来,",
|
||||
"success.subTitle": "应用已获得授权。你可以关闭此页面了",
|
||||
"success.subTitleWithCountdown": "应用已获得授权。{{countdown}}秒后自动关闭…",
|
||||
"success.title": "授权完成"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IconType, SiCaldotcom, SiGithub, SiLinear } from '@icons-pack/react-simple-icons';
|
||||
import { IconType, SiCaldotcom, SiGithub } from '@icons-pack/react-simple-icons';
|
||||
import { Klavis } from 'klavis';
|
||||
|
||||
export interface KlavisServerType {
|
||||
@@ -40,12 +40,6 @@ export const KLAVIS_SERVER_TYPES: KlavisServerType[] = [
|
||||
label: 'Airtable',
|
||||
serverName: Klavis.McpServerName.Airtable,
|
||||
},
|
||||
{
|
||||
icon: SiLinear,
|
||||
identifier: 'linear',
|
||||
label: 'Linear',
|
||||
serverName: Klavis.McpServerName.Linear,
|
||||
},
|
||||
{
|
||||
icon: 'https://hub-apac-1.lobeobjects.space/assets/logos/googlesheets.svg',
|
||||
identifier: 'google-sheets',
|
||||
|
||||
@@ -2,11 +2,48 @@
|
||||
|
||||
import { FluentEmoji, Text } from '@lobehub/ui';
|
||||
import { Result } from 'antd';
|
||||
import React, { memo } from 'react';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import React, { memo, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const SuccessPage = memo(() => {
|
||||
const { t } = useTranslation('oauth');
|
||||
const searchParams = useSearchParams();
|
||||
const [countdown, setCountdown] = useState(3);
|
||||
|
||||
useEffect(() => {
|
||||
// Check if this is a LobeHub Skill OAuth callback
|
||||
const provider = searchParams.get('provider');
|
||||
|
||||
if (provider && window.opener) {
|
||||
// Notify parent window about successful OAuth
|
||||
window.opener.postMessage(
|
||||
{
|
||||
provider,
|
||||
type: 'LOBEHUB_SKILL_AUTH_SUCCESS',
|
||||
},
|
||||
window.location.origin,
|
||||
);
|
||||
|
||||
// Start countdown and close window after 3 seconds
|
||||
let timeLeft = 3;
|
||||
setCountdown(timeLeft);
|
||||
|
||||
const countdownTimer = setInterval(() => {
|
||||
timeLeft -= 1;
|
||||
setCountdown(timeLeft);
|
||||
|
||||
if (timeLeft <= 0) {
|
||||
clearInterval(countdownTimer);
|
||||
window.close();
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
return () => clearInterval(countdownTimer);
|
||||
}
|
||||
}, [searchParams]);
|
||||
|
||||
const provider = searchParams.get('provider');
|
||||
|
||||
return (
|
||||
<Result
|
||||
@@ -14,7 +51,12 @@ const SuccessPage = memo(() => {
|
||||
status="success"
|
||||
subTitle={
|
||||
<Text fontSize={16} type="secondary">
|
||||
{t('success.subTitle')}
|
||||
{provider
|
||||
? t('success.subTitleWithCountdown', {
|
||||
countdown,
|
||||
defaultValue: `You may close this page. Auto-closing in ${countdown}s...`,
|
||||
})
|
||||
: t('success.subTitle')}
|
||||
</Text>
|
||||
}
|
||||
title={
|
||||
|
||||
@@ -135,13 +135,52 @@ const LobehubSkillServerItem = memo<LobehubSkillServerItemProps>(({ provider, la
|
||||
s.togglePlugin,
|
||||
]);
|
||||
|
||||
// Listen for OAuth success message from popup window
|
||||
useEffect(() => {
|
||||
const handleMessage = async (event: MessageEvent) => {
|
||||
// Verify origin for security
|
||||
if (event.origin !== window.location.origin) return;
|
||||
|
||||
if (event.data?.type === 'LOBEHUB_SKILL_AUTH_SUCCESS' && event.data?.provider === provider) {
|
||||
console.log('[LobehubSkill] OAuth success message received for provider:', provider);
|
||||
|
||||
// Cleanup polling/window monitoring
|
||||
cleanup();
|
||||
|
||||
// Refresh status to get the connected state
|
||||
await checkStatus(provider);
|
||||
|
||||
// Auto-enable the plugin after successful OAuth
|
||||
// Need to get the latest server state after checkStatus
|
||||
const latestServer = useToolStore
|
||||
.getState()
|
||||
.lobehubSkillServers?.find((s) => s.identifier === provider);
|
||||
if (latestServer?.status === LobehubSkillStatus.CONNECTED) {
|
||||
const newPluginId = latestServer.identifier;
|
||||
const isAlreadyEnabled = agentSelectors
|
||||
.currentAgentPlugins(useAgentStore.getState())
|
||||
.includes(newPluginId);
|
||||
if (!isAlreadyEnabled) {
|
||||
console.log('[LobehubSkill] Auto-enabling plugin:', newPluginId);
|
||||
togglePlugin(newPluginId);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('message', handleMessage);
|
||||
return () => window.removeEventListener('message', handleMessage);
|
||||
}, [provider, cleanup, checkStatus, togglePlugin]);
|
||||
|
||||
const handleConnect = async () => {
|
||||
// 只有已连接状态才阻止重新连接
|
||||
if (server?.isConnected) return;
|
||||
|
||||
setIsConnecting(true);
|
||||
try {
|
||||
const { authorizeUrl } = await getAuthorizeUrl(provider);
|
||||
// Use /oauth/callback/success as redirect URI with provider param for auto-enable
|
||||
const redirectUri = `${window.location.origin}/oauth/callback/success?provider=${encodeURIComponent(provider)}`;
|
||||
const { authorizeUrl } = await getAuthorizeUrl(provider, { redirectUri });
|
||||
openOAuthWindow(authorizeUrl);
|
||||
} catch (error) {
|
||||
console.error('[LobehubSkill] Failed to get authorize URL:', error);
|
||||
@@ -236,7 +275,8 @@ const LobehubSkillServerItem = memo<LobehubSkillServerItemProps>(({ provider, la
|
||||
onClick={async (e) => {
|
||||
e.stopPropagation();
|
||||
try {
|
||||
const { authorizeUrl } = await getAuthorizeUrl(provider);
|
||||
const redirectUri = `${window.location.origin}/oauth/callback/success?provider=${encodeURIComponent(provider)}`;
|
||||
const { authorizeUrl } = await getAuthorizeUrl(provider, { redirectUri });
|
||||
openOAuthWindow(authorizeUrl);
|
||||
} catch (error) {
|
||||
console.error('[LobehubSkill] Failed to get authorize URL:', error);
|
||||
|
||||
Reference in New Issue
Block a user