@@ -560,12 +560,85 @@ async def signal_camoufox_shutdown() -> None: # pragma: no cover
560560 )
561561
562562
563- async def enable_temporary_chat_mode (page : AsyncPage ) -> None : # pragma: no cover
563+ async def _is_temporary_chat_active (page : AsyncPage ) -> bool :
564+ """Best-effort check for whether Temporary chat is currently enabled.
565+
566+ Supports both the legacy toggle-class signal and the newer UI variants:
567+ - menu item checkmark (`data-test-incognito-checkmark`)
568+ - header indicator (`ms-incognito-mode-indicator`)
569+ """
570+
571+ try :
572+ # Newer UI: header indicator appears only when Temporary chat is active.
573+ indicator_locator = page .locator (
574+ "ms-incognito-mode-indicator [data-test-id='main-text'], "
575+ "ms-incognito-mode-indicator .main-text"
576+ )
577+ indicator_count = await indicator_locator .count ()
578+ for i in range (indicator_count ):
579+ try :
580+ indicator_item = indicator_locator .nth (i )
581+ if not await indicator_item .is_visible (timeout = 500 ):
582+ continue
583+ indicator_text = (await indicator_item .inner_text ()).strip ().lower ()
584+ if indicator_text == "temporary chat" :
585+ return True
586+ except Exception :
587+ continue
588+
589+ # Menu button variants (legacy and gray-release UI).
590+ toggle_locator = page .locator (
591+ "button[data-test-incognito-toggle], "
592+ 'button[aria-label="Temporary chat toggle"], '
593+ 'button[aria-label="Toggle temporary chat"]'
594+ )
595+ if await toggle_locator .count () > 0 :
596+ toggle_button = toggle_locator .first
597+
598+ # New UI: active state is represented by a checkmark inside the menu item.
599+ try :
600+ checkmark_locator = toggle_button .locator (
601+ "[data-test-incognito-checkmark]"
602+ )
603+ if (
604+ await checkmark_locator .count () > 0
605+ and await checkmark_locator .first .is_visible (timeout = 500 )
606+ ):
607+ return True
608+ except Exception :
609+ pass
610+
611+ # Legacy/alternative signals.
612+ for attr_name in ("aria-pressed" , "aria-checked" ):
613+ try :
614+ attr_value = await toggle_button .get_attribute (attr_name )
615+ if attr_value and attr_value .lower () == "true" :
616+ return True
617+ except Exception :
618+ pass
619+
620+ try :
621+ button_classes = await toggle_button .get_attribute ("class" ) or ""
622+ if "ms-button-active" in button_classes :
623+ return True
624+ except Exception :
625+ pass
626+
627+ return False
628+ except Exception :
629+ return False
630+
631+
632+ async def enable_temporary_chat_mode (page : AsyncPage ) -> bool : # pragma: no cover
564633 """
565634 Check and enable "Temporary chat" mode in the AI Studio interface.
566635 Supports both direct UI visibility and collapsed menu visibility.
567636 """
568- incognito_selector = 'button[aria-label="Temporary chat toggle"], button[aria-label="Toggle temporary chat"]'
637+ incognito_selector = (
638+ "button[data-test-incognito-toggle], "
639+ 'button[aria-label="Temporary chat toggle"], '
640+ 'button[aria-label="Toggle temporary chat"]'
641+ )
569642 menu_trigger_selector = 'button[aria-label="View more actions"]'
570643
571644 incognito_locator = page .locator (incognito_selector )
@@ -585,23 +658,23 @@ async def enable_temporary_chat_mode(page: AsyncPage) -> None: # pragma: no cov
585658 await incognito_locator .wait_for (state = "visible" , timeout = 5000 )
586659 else :
587660 logger .warning ("[UI] Neither button nor menu trigger found" )
588- return
589-
590- # Status Check
591- button_classes = await incognito_locator .get_attribute ("class" ) or ""
661+ return False
592662
593- if "ms-button-active" in button_classes :
663+ if await _is_temporary_chat_active ( page ) :
594664 logger .debug ("[UI] Temporary chat mode already active" )
595665 else :
596666 logger .debug ("[UI] Enabling temporary chat mode" )
597667 await incognito_locator .click (timeout = 5000 , force = True )
598668 await asyncio .sleep (1 )
599669
670+ enabled = await _is_temporary_chat_active (page )
671+
600672 # Recovery: Close menu if still expanded
601673 # Checking aria-expanded is more precise than a boolean flag
602674 if await menu_trigger .get_attribute ("aria-expanded" ) == "true" :
603675 logger .debug ("[UI] Closing menu to restore UI state" )
604676 await page .keyboard .press ("Escape" )
677+ return enabled
605678
606679 except asyncio .CancelledError :
607680 raise
@@ -610,3 +683,4 @@ async def enable_temporary_chat_mode(page: AsyncPage) -> None: # pragma: no cov
610683 # Final safety attempt to clear any stuck UI
611684 if await menu_trigger .get_attribute ("aria-expanded" ) == "true" :
612685 await page .keyboard .press ("Escape" )
686+ return await _is_temporary_chat_active (page )
0 commit comments