@@ -31,6 +31,7 @@ import {
3131 type ChatFormData ,
3232 useCreateChat ,
3333 useDeleteChat ,
34+ useRevealChatPassword ,
3435 useUpdateChat ,
3536} from '@/hooks/queries/chats'
3637import type { ChatDetail } from '@/hooks/queries/deployments'
@@ -41,6 +42,7 @@ import {
4142 getPasswordPlaceholder ,
4243 hasExistingPassword ,
4344 isPasswordRequired ,
45+ shouldConfirmPasswordChange ,
4446} from './utils'
4547
4648const logger = createLogger ( 'ChatDeploy' )
@@ -57,6 +59,7 @@ interface ChatDeployProps {
5759 onRefetchChat : ( ) => Promise < void >
5860 chatSubmitting : boolean
5961 setChatSubmitting : ( submitting : boolean ) => void
62+ canRevealPassword : boolean
6063 onValidationChange ?: ( isValid : boolean ) => void
6164 showDeleteConfirmation ?: boolean
6265 setShowDeleteConfirmation ?: ( show : boolean ) => void
@@ -97,6 +100,7 @@ export function ChatDeploy({
97100 onRefetchChat,
98101 chatSubmitting,
99102 setChatSubmitting,
103+ canRevealPassword,
100104 onValidationChange,
101105 showDeleteConfirmation : externalShowDeleteConfirmation ,
102106 setShowDeleteConfirmation : externalSetShowDeleteConfirmation ,
@@ -106,6 +110,7 @@ export function ChatDeploy({
106110} : ChatDeployProps ) {
107111 const [ imageUrl , setImageUrl ] = useState < string | null > ( null )
108112 const [ internalShowDeleteConfirmation , setInternalShowDeleteConfirmation ] = useState ( false )
113+ const [ showPasswordChangeConfirmation , setShowPasswordChangeConfirmation ] = useState ( false )
109114
110115 const showDeleteConfirmation =
111116 externalShowDeleteConfirmation !== undefined
@@ -213,9 +218,7 @@ export function ChatDeploy({
213218 }
214219 } , [ existingChat , isLoadingChat ] )
215220
216- const handleSubmit = async ( e ?: React . FormEvent ) => {
217- if ( e ) e . preventDefault ( )
218-
221+ const submitChat = async ( passwordChangeConfirmed = false ) => {
219222 if ( chatSubmitting ) return
220223
221224 setChatSubmitting ( true )
@@ -227,14 +230,20 @@ export function ChatDeploy({
227230 try {
228231 if ( ! validateForm ( ) ) {
229232 newTab ?. close ( )
230- setChatSubmitting ( false )
231233 return
232234 }
233235
234236 if ( ! isIdentifierValid && formData . identifier !== existingChat ?. identifier ) {
235237 newTab ?. close ( )
236238 setError ( 'identifier' , 'Please wait for identifier validation to complete' )
237- setChatSubmitting ( false )
239+ return
240+ }
241+
242+ if (
243+ ! passwordChangeConfirmed &&
244+ shouldConfirmPasswordChange ( Boolean ( existingChat ?. id ) , formData . authType , formData . password )
245+ ) {
246+ setShowPasswordChangeConfirmation ( true )
238247 return
239248 }
240249
@@ -283,6 +292,11 @@ export function ChatDeploy({
283292 }
284293 }
285294
295+ const handleSubmit = async ( event : React . FormEvent ) => {
296+ event . preventDefault ( )
297+ await submitChat ( )
298+ }
299+
286300 const handleDelete = async ( ) => {
287301 if ( ! existingChat || ! existingChat . id ) return
288302
@@ -306,6 +320,11 @@ export function ChatDeploy({
306320 }
307321 }
308322
323+ const handleConfirmPasswordChange = async ( ) => {
324+ setShowPasswordChangeConfirmation ( false )
325+ await submitChat ( true )
326+ }
327+
309328 if ( isLoadingChat ) {
310329 return < LoadingSkeleton />
311330 }
@@ -404,6 +423,8 @@ export function ChatDeploy({
404423
405424 < AuthSelector
406425 key = { `${ existingChat ?. id ?? 'new' } -${ formInitCounter } ` }
426+ chatId = { existingChat ?. id ?? null }
427+ canRevealPassword = { canRevealPassword }
407428 authType = { formData . authType }
408429 savedAuthType = { existingChat ?. authType as AuthType | undefined }
409430 password = { formData . password }
@@ -445,6 +466,21 @@ export function ChatDeploy({
445466 </ div >
446467 </ form >
447468
469+ < ChipConfirmModal
470+ open = { showPasswordChangeConfirmation }
471+ onOpenChange = { setShowPasswordChangeConfirmation }
472+ srTitle = 'Change deployment password'
473+ title = 'Change deployment password?'
474+ text = 'Are you sure you want to change the password for this deployment?'
475+ confirm = { {
476+ label : 'Change Password and Redeploy' ,
477+ onClick : handleConfirmPasswordChange ,
478+ variant : 'primary' ,
479+ pending : chatSubmitting ,
480+ pendingLabel : 'Updating...' ,
481+ } }
482+ />
483+
448484 < ChipConfirmModal
449485 open = { showDeleteConfirmation }
450486 onOpenChange = { setShowDeleteConfirmation }
@@ -617,6 +653,8 @@ function IdentifierInput({
617653}
618654
619655interface AuthSelectorProps {
656+ chatId : string | null
657+ canRevealPassword : boolean
620658 authType : AuthType
621659 /** The persisted mode of an existing chat, kept selectable even if newly disallowed. */
622660 savedAuthType ?: AuthType
@@ -638,6 +676,8 @@ const AUTH_LABELS: Record<AuthType, string> = {
638676}
639677
640678function AuthSelector ( {
679+ chatId,
680+ canRevealPassword,
641681 authType,
642682 savedAuthType,
643683 password,
@@ -651,6 +691,7 @@ function AuthSelector({
651691} : AuthSelectorProps ) {
652692 const [ emailError , setEmailError ] = useState ( '' )
653693 const [ invalidEmailItems , setInvalidEmailItems ] = useState < TagItem [ ] > ( [ ] )
694+ const revealPasswordMutation = useRevealChatPassword ( )
654695
655696 const emailsRef = useRef ( emails )
656697 const invalidEmailItemsRef = useRef ( invalidEmailItems )
@@ -756,9 +797,19 @@ function AuthSelector({
756797 value = { password }
757798 onChange = { onPasswordChange }
758799 disabled = { disabled }
759- placeholder = { getPasswordPlaceholder ( hasExistingPassword ) }
800+ placeholder = { hasExistingPassword ? '' : getPasswordPlaceholder ( false ) }
760801 required = { ! hasExistingPassword }
802+ fetchCurrentPassword = {
803+ canRevealPassword && chatId && hasExistingPassword
804+ ? ( ) => revealPasswordMutation . mutateAsync ( { chatId } )
805+ : undefined
806+ }
761807 />
808+ { canRevealPassword && revealPasswordMutation . isError && (
809+ < p className = 'mt-[6.5px] text-[var(--text-error)] text-caption' >
810+ Failed to load the current password
811+ </ p >
812+ ) }
762813 < p className = 'mt-[6.5px] text-[var(--text-secondary)] text-xs' >
763814 { getPasswordHelperText ( hasExistingPassword ) }
764815 </ p >
0 commit comments