fix: restore default channel connection paste
This commit is contained in:
+130
-20
@@ -24,6 +24,7 @@ import {
|
||||
Boxes,
|
||||
CheckCircle2,
|
||||
Circle,
|
||||
ClipboardPaste,
|
||||
HelpCircle,
|
||||
KeyRound,
|
||||
Loader2,
|
||||
@@ -115,6 +116,10 @@ import {
|
||||
ADMIN_PERMISSION_RESOURCES,
|
||||
hasPermission,
|
||||
} from '@/lib/admin-permissions'
|
||||
import {
|
||||
parseChannelConnectionInfo,
|
||||
type ChannelConnectionInfo,
|
||||
} from '@/lib/channel-connection-info'
|
||||
import { getLobeIcon } from '@/lib/lobe-icon'
|
||||
import { ROLE } from '@/lib/roles'
|
||||
import { cn } from '@/lib/utils'
|
||||
@@ -626,6 +631,8 @@ export function ChannelMutateDrawer({
|
||||
const [paramOverrideEditorOpen, setParamOverrideEditorOpen] = useState(false)
|
||||
const [advancedCustomEditorOpen, setAdvancedCustomEditorOpen] =
|
||||
useState(false)
|
||||
const [clipboardConnectionInfo, setClipboardConnectionInfo] =
|
||||
useState<ChannelConnectionInfo | null>(null)
|
||||
|
||||
const isEditing = Boolean(currentRow)
|
||||
const channelId = currentRow?.id ?? null
|
||||
@@ -757,6 +764,67 @@ export function ChannelMutateDrawer({
|
||||
}
|
||||
}, [open, resetDoubaoApiUnlock])
|
||||
|
||||
const applyConnectionInfo = useCallback(
|
||||
(connectionInfo: ChannelConnectionInfo) => {
|
||||
form.setValue('key', connectionInfo.key, {
|
||||
shouldDirty: true,
|
||||
shouldValidate: true,
|
||||
})
|
||||
form.setValue('base_url', connectionInfo.url, {
|
||||
shouldDirty: true,
|
||||
shouldValidate: true,
|
||||
})
|
||||
setClipboardConnectionInfo(null)
|
||||
toast.success(t('Connection info filled in'))
|
||||
},
|
||||
[form, t]
|
||||
)
|
||||
|
||||
const pasteConnectionInfoFromClipboard = useCallback(async () => {
|
||||
if (typeof navigator === 'undefined' || !navigator.clipboard?.readText) {
|
||||
toast.error(t('Unable to read clipboard'))
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const text = await navigator.clipboard.readText()
|
||||
const parsed = parseChannelConnectionInfo(text)
|
||||
if (parsed) {
|
||||
applyConnectionInfo(parsed)
|
||||
return
|
||||
}
|
||||
toast.info(t('No connection info found in clipboard'))
|
||||
} catch {
|
||||
toast.error(t('Unable to read clipboard'))
|
||||
}
|
||||
}, [applyConnectionInfo, t])
|
||||
|
||||
useEffect(() => {
|
||||
if (!open || isEditing) {
|
||||
setClipboardConnectionInfo(null)
|
||||
return
|
||||
}
|
||||
|
||||
if (typeof navigator === 'undefined' || !navigator.clipboard?.readText) {
|
||||
return
|
||||
}
|
||||
|
||||
let cancelled = false
|
||||
void navigator.clipboard
|
||||
.readText()
|
||||
.then((text) => {
|
||||
if (cancelled) return
|
||||
setClipboardConnectionInfo(parseChannelConnectionInfo(text))
|
||||
})
|
||||
.catch(() => {
|
||||
/* Clipboard detection is best-effort on drawer open. */
|
||||
})
|
||||
|
||||
return () => {
|
||||
cancelled = true
|
||||
}
|
||||
}, [isEditing, open])
|
||||
|
||||
// Helper computed values
|
||||
const isBatchMode =
|
||||
multiKeyMode === 'batch' || multiKeyMode === 'multi_to_single'
|
||||
@@ -1741,6 +1809,7 @@ export function ChannelMutateDrawer({
|
||||
setActiveEditorSectionId(CHANNEL_EDITOR_SECTION_IDS.identity)
|
||||
setExpandedEditorNavItemId(undefined)
|
||||
setAdvancedSettingsOpen(false)
|
||||
setClipboardConnectionInfo(null)
|
||||
}
|
||||
},
|
||||
[onOpenChange, form]
|
||||
@@ -1751,26 +1820,42 @@ export function ChannelMutateDrawer({
|
||||
<Sheet open={open} onOpenChange={handleOpenChange}>
|
||||
<SheetContent className={sideDrawerContentClassName('sm:max-w-5xl')}>
|
||||
<SheetHeader className={sideDrawerHeaderClassName()}>
|
||||
<SheetTitle className='flex items-center gap-3'>
|
||||
<span className='bg-muted flex size-9 shrink-0 items-center justify-center rounded-md'>
|
||||
<ChannelTypeLogo type={currentType} size={22} />
|
||||
</span>
|
||||
<span>
|
||||
{isEditing ? t('Edit Channel') : t('Create Channel')}
|
||||
<span className='text-muted-foreground ml-2 text-sm font-normal'>
|
||||
{t(currentTypeLabel)}
|
||||
</span>
|
||||
</span>
|
||||
</SheetTitle>
|
||||
<SheetDescription>
|
||||
{isEditing
|
||||
? t(
|
||||
"Update channel configuration and click save when you're done."
|
||||
)
|
||||
: t(
|
||||
'Add a new channel by providing the necessary information.'
|
||||
)}
|
||||
</SheetDescription>
|
||||
<div className='flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between'>
|
||||
<div className='min-w-0'>
|
||||
<SheetTitle className='flex items-center gap-3'>
|
||||
<span className='bg-muted flex size-9 shrink-0 items-center justify-center rounded-md'>
|
||||
<ChannelTypeLogo type={currentType} size={22} />
|
||||
</span>
|
||||
<span>
|
||||
{isEditing ? t('Edit Channel') : t('Create Channel')}
|
||||
<span className='text-muted-foreground ml-2 text-sm font-normal'>
|
||||
{t(currentTypeLabel)}
|
||||
</span>
|
||||
</span>
|
||||
</SheetTitle>
|
||||
<SheetDescription className='mt-1'>
|
||||
{isEditing
|
||||
? t(
|
||||
"Update channel configuration and click save when you're done."
|
||||
)
|
||||
: t(
|
||||
'Add a new channel by providing the necessary information.'
|
||||
)}
|
||||
</SheetDescription>
|
||||
</div>
|
||||
{!isEditing && (
|
||||
<Button
|
||||
type='button'
|
||||
variant='outline'
|
||||
size='sm'
|
||||
className='shrink-0'
|
||||
onClick={pasteConnectionInfoFromClipboard}
|
||||
>
|
||||
<ClipboardPaste className='size-4' />
|
||||
<span>{t('Paste Connection Info')}</span>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</SheetHeader>
|
||||
|
||||
{sensitiveLocked && (
|
||||
@@ -1786,6 +1871,31 @@ export function ChannelMutateDrawer({
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
{!isEditing && clipboardConnectionInfo && (
|
||||
<Alert>
|
||||
<AlertDescription className='flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between'>
|
||||
<span>{t('Connection info detected in clipboard')}</span>
|
||||
<span className='flex shrink-0 gap-2'>
|
||||
<Button
|
||||
type='button'
|
||||
size='sm'
|
||||
onClick={() => applyConnectionInfo(clipboardConnectionInfo)}
|
||||
>
|
||||
{t('Fill in')}
|
||||
</Button>
|
||||
<Button
|
||||
type='button'
|
||||
variant='ghost'
|
||||
size='sm'
|
||||
onClick={() => setClipboardConnectionInfo(null)}
|
||||
>
|
||||
{t('Ignore')}
|
||||
</Button>
|
||||
</span>
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<Form {...form}>
|
||||
<form
|
||||
id='channel-form'
|
||||
|
||||
@@ -50,6 +50,7 @@ import {
|
||||
import { useChatPresets } from '@/features/chat/hooks/use-chat-presets'
|
||||
import { resolveChatUrl, type ChatPreset } from '@/features/chat/lib/chat-links'
|
||||
import { sendToFluent } from '@/features/chat/lib/send-to-fluent'
|
||||
import { encodeChannelConnectionInfo } from '@/lib/channel-connection-info'
|
||||
import { copyToClipboard } from '@/lib/copy-to-clipboard'
|
||||
|
||||
import { updateApiKeyStatus } from '../api'
|
||||
@@ -70,14 +71,6 @@ function getServerAddress(): string {
|
||||
return window.location.origin
|
||||
}
|
||||
|
||||
function encodeConnectionString(key: string, url: string): string {
|
||||
return JSON.stringify({
|
||||
_type: 'newapi_channel_conn',
|
||||
key,
|
||||
url,
|
||||
})
|
||||
}
|
||||
|
||||
type DataTableRowActionsProps<TData> = {
|
||||
row: Row<TData>
|
||||
}
|
||||
@@ -262,7 +255,10 @@ export function DataTableRowActions<TData>({
|
||||
onClick={async () => {
|
||||
const realKey = getCachedRealKey()
|
||||
if (!realKey) return
|
||||
const connStr = encodeConnectionString(realKey, getServerAddress())
|
||||
const connStr = encodeChannelConnectionInfo(
|
||||
realKey,
|
||||
getServerAddress()
|
||||
)
|
||||
const ok = await copyToClipboard(connStr)
|
||||
if (ok) toast.success(t('Copied'))
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user