@@ -380,7 +380,6 @@ import kotlinx.coroutines.flow.debounce
380380import kotlinx.coroutines.flow.distinctUntilChanged
381381import kotlinx.coroutines.flow.distinctUntilChangedBy
382382import kotlinx.coroutines.flow.drop
383- import kotlinx.coroutines.flow.emptyFlow
384383import kotlinx.coroutines.flow.filter
385384import kotlinx.coroutines.flow.flatMapLatest
386385import kotlinx.coroutines.flow.flowOn
@@ -677,6 +676,7 @@ class BrowserTabViewModel @Inject constructor(
677676 }
678677
679678 init {
679+ logcat { " Duck.ai: init" }
680680 initializeViewStates()
681681
682682 fireproofWebsiteState.observeForever(fireproofWebsitesObserver)
@@ -775,33 +775,24 @@ class BrowserTabViewModel @Inject constructor(
775775 }.launchIn(viewModelScope)
776776
777777 // auto-launch input screen for new, empty tabs (New Tab Page)
778- combine(
779- externalIntentProcessingState.hasPendingTabLaunch,
780- externalIntentProcessingState.hasPendingDuckAiOpen,
781- ) { hasPendingTabLaunch, hasPendingDuckAiOpen ->
782- hasPendingTabLaunch || hasPendingDuckAiOpen
783- }.flatMapLatest {
784- if (it) {
785- // suppress auto-launch while processing external intents (for example, opening links from other apps)
786- // this prevents the New Tab Page from incorrectly triggering the input screen when the app
787- // is started via external intent while previously left on NTP
788- emptyFlow()
789- } else {
790- tabRepository.flowSelectedTab
791- .distinctUntilChangedBy { selectedTab -> selectedTab?.tabId } // only observe when the tab changes and ignore further updates
792- .filter { selectedTab ->
793- // fire event when activating a new, empty tab
794- // (has no URL and wasn't opened from another tab)
795- val showInputScreenAutomatically = duckAiFeatureState.showInputScreenAutomaticallyOnNewTab.value
796- val isActiveTab = ::tabId.isInitialized && selectedTab?.tabId == tabId
797- val isOpenedFromAnotherTab = selectedTab?.sourceTabId != null
798- showInputScreenAutomatically && isActiveTab && selectedTab?.url.isNullOrBlank() && ! isOpenedFromAnotherTab
799- }.flowOn(dispatchers.main()) // don't use the immediate dispatcher so that the tabId field has a chance to initialize
800- }
801- }.onEach {
802- // whenever an event fires, so the user switched to a new tab page, launch the input screen
803- command.value = LaunchInputScreen
804- }.launchIn(viewModelScope)
778+ tabRepository.flowSelectedTab
779+ .distinctUntilChangedBy { selectedTab -> selectedTab?.tabId } // only observe when the tab changes and ignore further updates
780+ .filter { selectedTab ->
781+ // fire event when activating a new, empty tab
782+ // (has no URL and wasn't opened from another tab)
783+ val showInputScreenAutomatically = duckAiFeatureState.showInputScreenAutomaticallyOnNewTab.value
784+ val isActiveTab = ::tabId.isInitialized && selectedTab?.tabId == tabId
785+ val isOpenedFromAnotherTab = selectedTab?.sourceTabId != null
786+ showInputScreenAutomatically && isActiveTab && selectedTab?.url.isNullOrBlank() && ! isOpenedFromAnotherTab
787+ }.flowOn(dispatchers.main()) // don't use the immediate dispatcher so that the tabId field has a chance to initialize
788+ .onEach {
789+ val hasPendingTabLaunch = externalIntentProcessingState.hasPendingTabLaunch.value
790+ val hasPendingDuckAiOpen = externalIntentProcessingState.hasPendingDuckAiOpen.value
791+ if (! hasPendingTabLaunch && ! hasPendingDuckAiOpen) {
792+ // whenever an event fires, so the user switched to a new tab page, launch the input screen
793+ command.value = LaunchInputScreen
794+ }
795+ }.launchIn(viewModelScope)
805796 }
806797
807798 fun loadData (
@@ -2148,9 +2139,9 @@ class BrowserTabViewModel @Inject constructor(
21482139 currentLoadingViewState().copy(
21492140 isLoading = true ,
21502141 trackersAnimationEnabled = true ,
2151- /* We set the progress to 20 so the omnibar starts animating and the user knows we are loading the page.
2152- * We don't show the browser until the page actually starts loading, to prevent previous sites from briefly
2153- * showing in case the URL was blocked locally and therefore never started to show*/
2142+ /* We set the progress to 20 so the omnibar starts animating and the user knows we are loading the page.
2143+ * We don't show the browser until the page actually starts loading, to prevent previous sites from briefly
2144+ * showing in case the URL was blocked locally and therefore never started to show*/
21542145 progress = 20 ,
21552146 url = documentUrlString,
21562147 )
@@ -2988,8 +2979,12 @@ class BrowserTabViewModel @Inject constructor(
29882979 // we hide the keyboard when showing a DialogCta and HomeCta type in the home screen otherwise we show it
29892980 val shouldHideKeyboard =
29902981 cta is HomePanelCta || cta is DaxBubbleCta .DaxPrivacyProCta ||
2991- duckAiFeatureState.showInputScreen.value || currentBrowserViewState().lastQueryOrigin == QueryOrigin .FromBookmark
2992- command.value = if (shouldHideKeyboard || (settingsDataStore.omnibarType == OmnibarType .SPLIT && alreadyShownKeyboard)) {
2982+ duckAiFeatureState.showInputScreen.value || currentBrowserViewState().lastQueryOrigin == QueryOrigin .FromBookmark ||
2983+ (settingsDataStore.omnibarType == OmnibarType .SPLIT && alreadyShownKeyboard)
2984+
2985+ logcat { " Duck.ai: shouldHideKeyboard: $shouldHideKeyboard " }
2986+
2987+ command.value = if (shouldHideKeyboard) {
29932988 HideKeyboard
29942989 } else {
29952990 alreadyShownKeyboard = true
@@ -3006,6 +3001,7 @@ class BrowserTabViewModel @Inject constructor(
30063001 is HomePanelCta .AddWidgetAuto , is HomePanelCta .AddWidgetAutoOnboardingExperiment , is HomePanelCta .AddWidgetInstructions -> {
30073002 LaunchAddWidget
30083003 }
3004+
30093005 is OnboardingDaxDialogCta -> onOnboardingCtaOkButtonClicked(cta)
30103006 is DaxBubbleCta -> onDaxBubbleCtaOkButtonClicked(cta)
30113007 is BrokenSitePromptDialogCta -> onBrokenSiteCtaOkButtonClicked(cta)
@@ -3299,7 +3295,10 @@ class BrowserTabViewModel @Inject constructor(
32993295 }
33003296
33013297 @SuppressLint(" RequiresFeature" , " PostMessageUsage" ) // it's already checked in isBlobDownloadWebViewFeatureEnabled
3302- private fun postMessageToConvertBlobToDataUri (webView : WebView , url : String ) {
3298+ private fun postMessageToConvertBlobToDataUri (
3299+ webView : WebView ,
3300+ url : String ,
3301+ ) {
33033302 viewModelScope.launch(dispatchers.main()) {
33043303 // main because postMessage is not always safe in another thread
33053304 for ((key, proxies) in fixedReplyProxyMap) {
@@ -3815,6 +3814,7 @@ class BrowserTabViewModel @Inject constructor(
38153814 if (id != null && data != null ) {
38163815 webViewCompatWebShare(featureName, method, id, data, onResponse)
38173816 }
3817+
38183818 " permissionsQuery" ->
38193819 if (id != null && data != null ) {
38203820 webViewCompatPermissionsQuery(featureName, method, id, data, onResponse)
@@ -3828,6 +3828,7 @@ class BrowserTabViewModel @Inject constructor(
38283828 " screenUnlock" -> screenUnlock()
38293829 }
38303830 }
3831+
38313832 " breakageReporting" ->
38323833 if (data != null ) {
38333834 when (method) {
@@ -3836,6 +3837,7 @@ class BrowserTabViewModel @Inject constructor(
38363837 }
38373838 }
38383839 }
3840+
38393841 " messaging" ->
38403842 when (method) {
38413843 " initialPing" -> {
@@ -4381,10 +4383,12 @@ class BrowserTabViewModel @Inject constructor(
43814383 onboardingDesignExperimentManager.isBuckEnrolledAndEnabled() -> {
43824384 command.value = SetBrowserBackgroundColor (getBuckOnboardingExperimentBackgroundColor(lightModeEnabled))
43834385 }
4386+
43844387 onboardingDesignExperimentManager.isBbEnrolledAndEnabled() -> {
43854388 // TODO if BB wins the we should rename the function to SetBubbleDialogBackground
43864389 command.value = Command .SetBubbleDialogBackground (getBBBackgroundResource(lightModeEnabled))
43874390 }
4391+
43884392 else -> {
43894393 command.value = SetBrowserBackground (getBackgroundResource(lightModeEnabled))
43904394 }
@@ -4403,9 +4407,11 @@ class BrowserTabViewModel @Inject constructor(
44034407 onboardingDesignExperimentManager.isBuckEnrolledAndEnabled() -> {
44044408 command.value = SetOnboardingDialogBackgroundColor (getBuckOnboardingExperimentBackgroundColor(lightModeEnabled))
44054409 }
4410+
44064411 onboardingDesignExperimentManager.isBbEnrolledAndEnabled() -> {
44074412 command.value = SetOnboardingDialogBackground (getBBBackgroundResource(lightModeEnabled))
44084413 }
4414+
44094415 else -> {
44104416 command.value = SetOnboardingDialogBackground (getBackgroundResource(lightModeEnabled))
44114417 }
@@ -4470,14 +4476,17 @@ class BrowserTabViewModel @Inject constructor(
44704476 command.value = LaunchPrivacyPro (" https://duckduckgo.com/pro?origin=funnel_appmenu_android" .toUri())
44714477 " pill"
44724478 }
4479+
44734480 VpnMenuState .NotSubscribedNoPill -> {
44744481 command.value = LaunchPrivacyPro (" https://duckduckgo.com/pro?origin=funnel_appmenu_android" .toUri())
44754482 " no_pill"
44764483 }
4484+
44774485 is VpnMenuState .Subscribed -> {
44784486 command.value = LaunchVpnManagement
44794487 " subscribed"
44804488 }
4489+
44814490 VpnMenuState .Hidden -> " " // Should not happen as menu item should not be visible
44824491 }
44834492 pixel.fire(AppPixelName .MENU_ACTION_VPN_PRESSED , mapOf (PixelParameter .STATUS to statusParam))
0 commit comments