@@ -505,6 +505,10 @@ const inputHighlightEl = document.getElementById('input-highlight');
505505const sendBtn = document . getElementById ( 'btn-send' ) ;
506506const micBtn = document . getElementById ( 'btn-mic' ) ;
507507const clearBtn = document . getElementById ( 'btn-clear' ) ;
508+ const appEl = document . getElementById ( 'app' ) ;
509+ const newConversationConfirmEl = document . getElementById ( 'new-conversation-confirm' ) ;
510+ const newConversationConfirmCancelBtn = document . getElementById ( 'new-conversation-confirm-cancel' ) ;
511+ const newConversationConfirmAcceptBtn = document . getElementById ( 'new-conversation-confirm-accept' ) ;
508512const historyBtn = document . getElementById ( 'btn-history' ) ;
509513const settingsBtn = document . getElementById ( 'btn-settings' ) ;
510514const verboseBtn = document . getElementById ( 'btn-verbose' ) ;
@@ -975,6 +979,7 @@ const awaitingPlanReviewTabs = new Set();
975979const processingTabs = new Set ( ) ;
976980const abortRequestedTabs = new Set ( ) ;
977981const clearingConversationTabs = new Set ( ) ;
982+ let newConversationConfirmationState = null ;
978983const localRunRequestIds = new Map ( ) ;
979984const localRunFollowers = new Map ( ) ;
980985const cancelledRunRecoveryRequestIds = new Set ( ) ;
@@ -1021,6 +1026,86 @@ function isConversationClearInProgress(tabId = currentTabId) {
10211026 return Number . isFinite ( numericTabId ) && clearingConversationTabs . has ( numericTabId ) ;
10221027}
10231028
1029+ function settleNewConversationConfirmation ( confirmed , { restoreFocus = true } = { } ) {
1030+ const state = newConversationConfirmationState ;
1031+ if ( ! state ) return ;
1032+ newConversationConfirmationState = null ;
1033+ newConversationConfirmEl ?. classList . add ( 'hidden' ) ;
1034+ if ( appEl ) appEl . inert = state . appWasInert ;
1035+ if ( restoreFocus && state . previouslyFocusedElement ?. isConnected
1036+ && typeof state . previouslyFocusedElement . focus === 'function' ) {
1037+ state . previouslyFocusedElement . focus ( { preventScroll : true } ) ;
1038+ }
1039+ state . resolve ( ! ! confirmed ) ;
1040+ }
1041+
1042+ function requestNewConversationConfirmation ( tabId ) {
1043+ if ( newConversationConfirmationState || ! appEl || ! newConversationConfirmEl
1044+ || ! newConversationConfirmCancelBtn || ! newConversationConfirmAcceptBtn ) {
1045+ return Promise . resolve ( false ) ;
1046+ }
1047+
1048+ let resolveConfirmation ;
1049+ const promise = new Promise ( ( resolve ) => {
1050+ resolveConfirmation = resolve ;
1051+ } ) ;
1052+ newConversationConfirmationState = {
1053+ tabId : Number ( tabId ) ,
1054+ promise,
1055+ resolve : resolveConfirmation ,
1056+ appWasInert : appEl . inert ,
1057+ previouslyFocusedElement : document . activeElement ,
1058+ } ;
1059+
1060+ applyDOMTranslations ( newConversationConfirmEl ) ;
1061+ appEl . inert = true ;
1062+ newConversationConfirmEl . classList . remove ( 'hidden' ) ;
1063+ newConversationConfirmCancelBtn . focus ( { preventScroll : true } ) ;
1064+ return promise ;
1065+ }
1066+
1067+ function handleNewConversationConfirmKeydown ( event ) {
1068+ if ( ! newConversationConfirmationState ) return false ;
1069+
1070+ if ( event . key === 'Escape' ) {
1071+ event . preventDefault ( ) ;
1072+ settleNewConversationConfirmation ( false ) ;
1073+ } else if ( event . key === 'Tab' ) {
1074+ const focusable = Array . from ( newConversationConfirmEl . querySelectorAll (
1075+ '[data-new-conversation-confirm-action]:not([disabled])' ,
1076+ ) ) ;
1077+ if ( ! focusable . length ) {
1078+ event . preventDefault ( ) ;
1079+ newConversationConfirmEl . focus ( { preventScroll : true } ) ;
1080+ } else {
1081+ const first = focusable [ 0 ] ;
1082+ const last = focusable [ focusable . length - 1 ] ;
1083+ const activeElement = document . activeElement ;
1084+ if ( event . shiftKey && ( activeElement === first || ! newConversationConfirmEl . contains ( activeElement ) ) ) {
1085+ event . preventDefault ( ) ;
1086+ last . focus ( { preventScroll : true } ) ;
1087+ } else if ( ! event . shiftKey && ( activeElement === last || ! newConversationConfirmEl . contains ( activeElement ) ) ) {
1088+ event . preventDefault ( ) ;
1089+ first . focus ( { preventScroll : true } ) ;
1090+ }
1091+ }
1092+ }
1093+
1094+ event . stopImmediatePropagation ( ) ;
1095+ return true ;
1096+ }
1097+
1098+ document . addEventListener ( 'keydown' , handleNewConversationConfirmKeydown , true ) ;
1099+ newConversationConfirmCancelBtn ?. addEventListener ( 'click' , ( ) => {
1100+ settleNewConversationConfirmation ( false ) ;
1101+ } ) ;
1102+ newConversationConfirmAcceptBtn ?. addEventListener ( 'click' , ( ) => {
1103+ settleNewConversationConfirmation ( true ) ;
1104+ } ) ;
1105+ newConversationConfirmEl ?. addEventListener ( 'click' , ( event ) => {
1106+ if ( event . target === newConversationConfirmEl ) settleNewConversationConfirmation ( false ) ;
1107+ } ) ;
1108+
10241109function setTabAbortRequested ( tabId , requested ) {
10251110 const numericTabId = Number ( tabId ) ;
10261111 if ( ! Number . isFinite ( numericTabId ) ) return ;
@@ -3542,6 +3627,10 @@ if (verboseBtn) {
35423627
35433628async function switchToTab ( newTabId ) {
35443629 if ( newTabId === currentTabId && renderedTabId === newTabId ) { return ; }
3630+ if ( newConversationConfirmationState
3631+ && ! sameTabId ( newConversationConfirmationState . tabId , newTabId ) ) {
3632+ settleNewConversationConfirmation ( false , { restoreFocus : false } ) ;
3633+ }
35453634 const switchGeneration = ++ tabSwitchGeneration ;
35463635 tabSwitchTransitionId = newTabId ;
35473636 queuedTabSwitchMessages = [ ] ;
@@ -10291,8 +10380,9 @@ document.addEventListener('wb-locale-changed', () => {
1029110380
1029210381clearBtn . addEventListener ( 'click' , async ( ) => {
1029310382 const tabId = currentTabId ;
10294- if ( isConversationClearInProgress ( tabId ) ) return ;
10295- if ( ! window . confirm ( t ( 'sp.clear.confirm' ) ) ) return ;
10383+ if ( isConversationClearInProgress ( tabId ) || newConversationConfirmationState ) return ;
10384+ if ( ! await requestNewConversationConfirmation ( tabId ) ) return ;
10385+ if ( ! sameTabId ( currentTabId , tabId ) ) return ;
1029610386 setConversationClearInProgress ( tabId , true ) ;
1029710387 try {
1029810388 suppressRunUpdatesForClearedConversation ( tabId ) ;
0 commit comments