diff --git a/packages/cli/src/ui/components/QwenOAuthProgress.tsx b/packages/cli/src/ui/components/QwenOAuthProgress.tsx
index 10977fe8..f1664215 100644
--- a/packages/cli/src/ui/components/QwenOAuthProgress.tsx
+++ b/packages/cli/src/ui/components/QwenOAuthProgress.tsx
@@ -4,8 +4,8 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import React, { useState, useEffect } from 'react';
-import { Box, Text, useInput, Static } from 'ink';
+import React, { useState, useEffect, useMemo } from 'react';
+import { Box, Text, useInput } from 'ink';
import Spinner from 'ink-spinner';
import Link from 'ink-link';
import qrcode from 'qrcode-terminal';
@@ -26,17 +26,93 @@ interface QwenOAuthProgressProps {
authMessage?: string | null;
}
-interface StaticItem {
- key: string;
- type:
- | 'title'
- | 'instructions'
- | 'url'
- | 'qr-instructions'
- | 'qr-code'
- | 'auth-content';
- url?: string;
- qrCode?: string;
+/**
+ * Static QR Code Display Component
+ * Renders the QR code and URL once and doesn't re-render unless the URL changes
+ */
+function QrCodeDisplay({
+ verificationUrl,
+ qrCodeData,
+}: {
+ verificationUrl: string;
+ qrCodeData: string | null;
+}): React.JSX.Element | null {
+ if (!qrCodeData) {
+ return null;
+ }
+
+ return (
+
+
+ Qwen OAuth Authentication
+
+
+
+ Please visit this URL to authorize:
+
+
+
+
+ {verificationUrl}
+
+
+
+
+ Or scan the QR code below:
+
+
+
+ {qrCodeData}
+
+
+ );
+}
+
+/**
+ * Dynamic Status Display Component
+ * Shows the loading spinner, timer, and status messages
+ */
+function StatusDisplay({
+ timeRemaining,
+ dots,
+}: {
+ timeRemaining: number;
+ dots: string;
+}): React.JSX.Element {
+ const formatTime = (seconds: number): string => {
+ const minutes = Math.floor(seconds / 60);
+ const remainingSeconds = seconds % 60;
+ return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
+ };
+
+ return (
+
+
+
+ Waiting for authorization{dots}
+
+
+
+
+
+ Time remaining: {formatTime(timeRemaining)}
+
+ (Press ESC to cancel)
+
+
+ );
}
export function QwenOAuthProgress({
@@ -60,33 +136,29 @@ export function QwenOAuthProgress({
}
});
- // Generate QR code when device auth is available
+ // Generate QR code once when device auth is available
useEffect(() => {
- if (!deviceAuth) {
- setQrCodeData(null);
+ if (!deviceAuth?.verification_uri_complete) {
return;
}
- // Only generate QR code if we don't have one yet for this URL
- if (qrCodeData === null) {
- const generateQR = () => {
- try {
- qrcode.generate(
- deviceAuth.verification_uri_complete,
- { small: true },
- (qrcode: string) => {
- setQrCodeData(qrcode);
- },
- );
- } catch (error) {
- console.error('Failed to generate QR code:', error);
- setQrCodeData(null);
- }
- };
+ const generateQR = () => {
+ try {
+ qrcode.generate(
+ deviceAuth.verification_uri_complete,
+ { small: true },
+ (qrcode: string) => {
+ setQrCodeData(qrcode);
+ },
+ );
+ } catch (error) {
+ console.error('Failed to generate QR code:', error);
+ setQrCodeData(null);
+ }
+ };
- generateQR();
- }
- }, [deviceAuth, qrCodeData]);
+ generateQR();
+ }, [deviceAuth?.verification_uri_complete]);
// Countdown timer
useEffect(() => {
@@ -115,11 +187,17 @@ export function QwenOAuthProgress({
return () => clearInterval(dotsTimer);
}, []);
- const formatTime = (seconds: number): string => {
- const minutes = Math.floor(seconds / 60);
- const remainingSeconds = seconds % 60;
- return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
- };
+ // Memoize the QR code display to prevent unnecessary re-renders
+ const qrCodeDisplay = useMemo(() => {
+ if (!deviceAuth?.verification_uri_complete) return null;
+
+ return (
+
+ );
+ }, [deviceAuth?.verification_uri_complete, qrCodeData]);
// Handle timeout state
if (authStatus === 'timeout') {
@@ -151,6 +229,7 @@ export function QwenOAuthProgress({
);
}
+ // Show loading state when no device auth is available yet
if (!deviceAuth) {
return (
- Time remaining: {formatTime(timeRemaining)}
+ Time remaining: {Math.floor(timeRemaining / 60)}:
+ {(timeRemaining % 60).toString().padStart(2, '0')}
(Press ESC to cancel)
@@ -176,77 +256,12 @@ export function QwenOAuthProgress({
}
return (
- <>
- {qrCodeData && (
-
- {(item: StaticItem) => (
-
-
- Qwen OAuth Authentication
-
+
+ {/* Static QR Code Display */}
+ {qrCodeDisplay}
-
- Please visit this URL to authorize:
-
-
-
-
- {item.url || ''}
-
-
-
-
- Or scan the QR code below:
-
-
-
- {item.qrCode || ''}
-
-
- )}
-
- )}
-
-
-
- Waiting for authorization{dots}
-
-
-
-
-
- Time remaining: {formatTime(timeRemaining)}
-
- (Press ESC to cancel)
-
-
- >
+ {/* Dynamic Status Display */}
+
+
);
}