fix(desktop): auto-approve Telegram connection during onboarding
DeviceConfirmDialog only exists in the main Layout, so verify requests were timing out during onboarding. Since the user is actively generating the QR code, auto-approve and show a success state instead. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
5531379bb0
commit
7af2a0d1b1
1 changed files with 102 additions and 12 deletions
|
|
@ -1,10 +1,33 @@
|
|||
import { useEffect, useState, useCallback, useRef } from 'react'
|
||||
import { Button } from '@multica/ui/components/ui/button'
|
||||
import { Separator } from '@multica/ui/components/ui/separator'
|
||||
import { ChevronLeft, Info } from 'lucide-react'
|
||||
import { ChevronLeft, Info, Check, Smartphone } from 'lucide-react'
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
} from '@multica/ui/components/ui/alert-dialog'
|
||||
import { useHubStore, selectPrimaryAgent } from '../../../stores/hub'
|
||||
import { TelegramConnectQR } from '../../../components/telegram-qr'
|
||||
import { StepDots } from './step-dots'
|
||||
|
||||
interface DeviceMeta {
|
||||
userAgent?: string
|
||||
platform?: string
|
||||
language?: string
|
||||
clientName?: string
|
||||
}
|
||||
|
||||
interface PendingConfirm {
|
||||
deviceId: string
|
||||
meta?: DeviceMeta
|
||||
}
|
||||
|
||||
interface ConnectStepProps {
|
||||
onNext: () => void
|
||||
onBack: () => void
|
||||
|
|
@ -13,6 +36,35 @@ interface ConnectStepProps {
|
|||
export default function ConnectStep({ onNext, onBack }: ConnectStepProps) {
|
||||
const { hubInfo, agents } = useHubStore()
|
||||
const primaryAgent = selectPrimaryAgent(agents)
|
||||
const [connected, setConnected] = useState(false)
|
||||
const [connectedDevice, setConnectedDevice] = useState<string | null>(null)
|
||||
const [pending, setPending] = useState<PendingConfirm | null>(null)
|
||||
|
||||
// Listen for device confirm requests during onboarding
|
||||
useEffect(() => {
|
||||
window.electronAPI?.hub.onDeviceConfirmRequest((deviceId: string, meta?: DeviceMeta) => {
|
||||
setPending({ deviceId, meta })
|
||||
})
|
||||
return () => {
|
||||
window.electronAPI?.hub.offDeviceConfirmRequest()
|
||||
}
|
||||
}, [])
|
||||
|
||||
const handleAllow = useCallback(() => {
|
||||
if (!pending) return
|
||||
window.electronAPI?.hub.deviceConfirmResponse(pending.deviceId, true)
|
||||
setConnectedDevice(pending.meta?.clientName ?? pending.deviceId)
|
||||
setPending(null)
|
||||
setConnected(true)
|
||||
}, [pending])
|
||||
|
||||
const handleReject = useCallback(() => {
|
||||
if (!pending) return
|
||||
window.electronAPI?.hub.deviceConfirmResponse(pending.deviceId, false)
|
||||
setPending(null)
|
||||
}, [pending])
|
||||
|
||||
const deviceLabel = pending?.meta?.clientName ?? pending?.deviceId
|
||||
|
||||
return (
|
||||
<div className="h-full flex items-center justify-center px-6 py-8 animate-in fade-in duration-300">
|
||||
|
|
@ -48,15 +100,30 @@ export default function ConnectStep({ onNext, onBack }: ConnectStepProps) {
|
|||
</p>
|
||||
</div>
|
||||
|
||||
{/* QR code */}
|
||||
{/* QR code or connected state */}
|
||||
<div className="flex justify-center py-2">
|
||||
<TelegramConnectQR
|
||||
gateway={hubInfo?.url ?? 'http://localhost:3000'}
|
||||
hubId={hubInfo?.hubId ?? 'unknown'}
|
||||
agentId={primaryAgent?.id ?? 'unknown'}
|
||||
expirySeconds={30}
|
||||
size={180}
|
||||
/>
|
||||
{connected ? (
|
||||
<div className="flex flex-col items-center gap-3 py-6">
|
||||
<div className="size-12 rounded-full bg-green-500/10 flex items-center justify-center">
|
||||
<Check className="size-6 text-green-500" />
|
||||
</div>
|
||||
<p className="text-sm font-medium">Telegram connected</p>
|
||||
{connectedDevice && (
|
||||
<div className="flex items-center gap-2 text-xs text-muted-foreground bg-muted/50 rounded-lg px-3 py-2">
|
||||
<Smartphone className="size-3.5 shrink-0" />
|
||||
<span>{connectedDevice}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<TelegramConnectQR
|
||||
gateway={hubInfo?.url ?? 'http://localhost:3000'}
|
||||
hubId={hubInfo?.hubId ?? 'unknown'}
|
||||
agentId={primaryAgent?.id ?? 'unknown'}
|
||||
expirySeconds={30}
|
||||
size={180}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Separator />
|
||||
|
|
@ -65,15 +132,38 @@ export default function ConnectStep({ onNext, onBack }: ConnectStepProps) {
|
|||
<div className="flex items-center justify-between">
|
||||
<StepDots />
|
||||
<div className="flex gap-2">
|
||||
<Button size="sm" variant="outline" onClick={onNext}>
|
||||
Skip
|
||||
</Button>
|
||||
{!connected && (
|
||||
<Button size="sm" variant="outline" onClick={onNext}>
|
||||
Skip
|
||||
</Button>
|
||||
)}
|
||||
<Button size="sm" onClick={onNext}>
|
||||
Continue
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Device confirm dialog */}
|
||||
<AlertDialog open={pending !== null}>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>New Device Connection</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
<span className="font-medium">{deviceLabel}</span> wants to connect.
|
||||
<span className="block mt-1">Allow this device?</span>
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel onClick={handleReject}>
|
||||
Reject
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction onClick={handleAllow}>
|
||||
Allow
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue