@@ -2,6 +2,7 @@ import { useRenderer } from '@opentui/react'
22import open from 'open'
33import React , { useCallback , useEffect , useRef , useState } from 'react'
44
5+ import { Button } from './button'
56import { TerminalLink } from './terminal-link'
67import { useLoginMutation } from '../hooks/use-auth-query'
78import { useFetchLoginUrl } from '../hooks/use-fetch-login-url'
@@ -63,6 +64,9 @@ export const LoginModal = ({
6364 // Generate fingerprint ID (only once on mount)
6465 const [ fingerprintId ] = useState ( ( ) => generateFingerprintId ( ) )
6566
67+ // Track hover state for copy button
68+ const [ isCopyButtonHovered , setIsCopyButtonHovered ] = useState ( false )
69+
6670 // Use TanStack Query for login mutation
6771 const loginMutation = useLoginMutation ( )
6872
@@ -95,11 +99,8 @@ export const LoginModal = ({
9599 setJustCopied ( false )
96100 } , 3000 )
97101 } catch ( err ) {
102+ // Silently fail - the URL is visible for manual copying
98103 logger . error ( err , 'Failed to copy to clipboard' )
99- setCopyMessage ( '✗ Failed to copy to clipboard' )
100- setTimeout ( ( ) => {
101- setCopyMessage ( null )
102- } , 3000 )
103104 }
104105 } ,
105106 [ setHasClickedLink , setJustCopied , setCopyMessage ] ,
@@ -192,12 +193,6 @@ export const LoginModal = ({
192193 onCopyUrl : copyToClipboard ,
193194 } )
194195
195- // Auto-copy URL when browser is opened
196- useEffect ( ( ) => {
197- if ( hasOpenedBrowser && loginUrl ) {
198- copyToClipboard ( loginUrl )
199- }
200- } , [ hasOpenedBrowser , loginUrl , copyToClipboard ] )
201196
202197 // Calculate terminal width and height for responsive display
203198 const terminalWidth = renderer ?. width || 80
@@ -363,15 +358,13 @@ export const LoginModal = ({
363358 >
364359 < text style = { { wrapMode : 'word' } } >
365360 < span fg = { '#00cc00' } >
366- { isNarrow
367- ? 'Press ENTER to login...'
368- : 'Press ENTER to open your browser and login...' }
361+ Press ENTER to login...
369362 </ span >
370363 </ text >
371364 </ box >
372365 ) }
373366
374- { /* After opening browser - show URL as fallback */ }
367+ { /* After pressing enter - show URL prominently for all users */ }
375368 { ! loading && ! error && loginUrl && hasOpenedBrowser && (
376369 < box
377370 style = { {
@@ -384,15 +377,15 @@ export const LoginModal = ({
384377 } }
385378 >
386379 < text style = { { wrapMode : 'word' } } >
387- < span fg = { theme . secondary } >
380+ < span fg = { theme . foreground } >
388381 { isNarrow
389- ? 'Opening browser... '
390- : 'Opening browser to complete login... ' }
382+ ? 'Open this URL to login: '
383+ : 'Open this URL in your browser to login: ' }
391384 </ span >
392385 </ text >
393386 < box
394387 style = { {
395- marginTop : 0 ,
388+ marginTop : isVerySmall ? 1 : 2 ,
396389 width : '100%' ,
397390 flexShrink : 0 ,
398391 } }
@@ -401,7 +394,7 @@ export const LoginModal = ({
401394 text = { loginUrl }
402395 maxWidth = { maxUrlWidth }
403396 formatLines = { formatLoginUrlLines }
404- color = { hasClickedLink ? theme . success : theme . link }
397+ color = { theme . primary }
405398 activeColor = { theme . success }
406399 underlineOnHover = { true }
407400 isActive = { justCopied }
@@ -412,28 +405,35 @@ export const LoginModal = ({
412405 } }
413406 />
414407 </ box >
415- { copyMessage && (
416- < box
417- style = { {
418- marginTop : isVerySmall ? 0 : 1 ,
419- flexDirection : 'column' ,
420- alignItems : 'center' ,
421- width : '100%' ,
422- flexShrink : 0 ,
423- } }
408+ < box
409+ style = { {
410+ marginTop : isVerySmall ? 1 : 2 ,
411+ flexDirection : 'column' ,
412+ alignItems : 'center' ,
413+ width : '100%' ,
414+ flexShrink : 0 ,
415+ } }
416+ >
417+ < Button
418+ onClick = { ( ) => copyToClipboard ( loginUrl ) }
419+ onMouseOver = { ( ) => setIsCopyButtonHovered ( true ) }
420+ onMouseOut = { ( ) => setIsCopyButtonHovered ( false ) }
424421 >
425- < text style = { { wrapMode : 'none' } } >
422+ < text >
426423 < span
427424 fg = {
428- copyMessage . startsWith ( '✓' ) ? theme . success : theme . error
425+ justCopied
426+ ? theme . foreground
427+ : isCopyButtonHovered
428+ ? theme . foreground
429+ : theme . primary
429430 }
430431 >
431- { copyMessage }
432+ { justCopied ? '[ ✓ Copied! ]' : '[ Copy link (c) ]' }
432433 </ span >
433434 </ text >
434- </ box >
435- ) }
436- { /* Show raw URL as fallback for devices where open() doesn't work */ }
435+ </ Button >
436+ </ box >
437437 < box
438438 style = { {
439439 marginTop : isVerySmall ? 1 : 2 ,
@@ -443,14 +443,9 @@ export const LoginModal = ({
443443 flexShrink : 0 ,
444444 } }
445445 >
446- < text style = { { wrapMode : 'word' } } >
447- < span fg = { theme . muted } >
448- { isNarrow ? 'Or copy URL:' : "Or copy this URL if browser didn't open:" }
449- </ span >
450- </ text >
451- < text style = { { wrapMode : 'word' } } >
452- < span fg = { theme . muted } >
453- { loginUrl }
446+ < text style = { { wrapMode : 'none' } } >
447+ < span fg = { theme . secondary } >
448+ Waiting for login...
454449 </ span >
455450 </ text >
456451 </ box >
0 commit comments