Skip to content

Commit

Permalink
Improve back button handling in feedback (#4908)
Browse files Browse the repository at this point in the history
Task/Issue URL:
https://app.asana.com/0/488551667048375/1208045844925126/f

### Description
This PR contains the following:
- Fix for the back button bug in Browser Feedback
- Use OnBackPressedCallback instead of overriding onBackPressed in Ppro
unified feedback

### Steps to test this PR

_Browser Feedback_
- [x] Install build
- [x] Go to Settings > About > Share Feedback
- [x] Smoke test back button and it behaves accordingly

_PPro Unified Feedback_
Follow https://app.asana.com/0/0/1208071203780039/f
  • Loading branch information
karlenDimla authored Aug 16, 2024
1 parent e2ed0aa commit e408922
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import android.app.Activity.RESULT_OK
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.activity.OnBackPressedCallback
import androidx.fragment.app.FragmentTransaction
import androidx.fragment.app.transaction
import com.duckduckgo.anvil.annotations.ContributeToActivityStarter
Expand Down Expand Up @@ -64,6 +65,14 @@ class FeedbackActivity :
setContentView(binding.root)
setupToolbar(toolbar)
configureObservers()
onBackPressedDispatcher.addCallback(
this,
object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
viewModel.onBackPressed()
}
},
)
}

private fun configureObservers() {
Expand Down Expand Up @@ -153,11 +162,6 @@ class FeedbackActivity :
}
}

override fun onBackPressed() {
super.onBackPressed()
viewModel.onBackPressed()
}

/**
* Initial feedback page listeners
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package com.duckduckgo.subscriptions.impl.feedback

import android.os.Bundle
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.annotation.StringRes
import androidx.fragment.app.commit
import androidx.lifecycle.Lifecycle
Expand All @@ -38,6 +39,7 @@ import com.duckduckgo.subscriptions.api.PrivacyProFeedbackScreens.PrivacyProFeed
import com.duckduckgo.subscriptions.impl.R
import com.duckduckgo.subscriptions.impl.databinding.ActivityFeedbackBinding
import com.duckduckgo.subscriptions.impl.feedback.SubscriptionFeedbackViewModel.Command
import com.duckduckgo.subscriptions.impl.feedback.SubscriptionFeedbackViewModel.Command.FeedbackCancelled
import com.duckduckgo.subscriptions.impl.feedback.SubscriptionFeedbackViewModel.Command.FeedbackCompleted
import com.duckduckgo.subscriptions.impl.feedback.SubscriptionFeedbackViewModel.Command.ShowHelpPages
import com.duckduckgo.subscriptions.impl.feedback.SubscriptionFeedbackViewModel.FeedbackFragmentState
Expand Down Expand Up @@ -76,14 +78,14 @@ class SubscriptionFeedbackActivity :
setupToolbar(toolbar)
observeViewModel()
handleInitialState()
}

override fun onBackPressed() {
if (viewModel.shouldGoBackInFeedbackFlow()) {
viewModel.handleBackInFlow()
} else {
super.onBackPressed()
}
onBackPressedDispatcher.addCallback(
this,
object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
viewModel.handleBackPress()
}
},
)
}

private fun handleInitialState() {
Expand Down Expand Up @@ -149,6 +151,7 @@ class SubscriptionFeedbackActivity :

private fun handleCommands(command: Command) {
when (command) {
is FeedbackCancelled -> finish()
is FeedbackCompleted -> {
Toast.makeText(applicationContext, R.string.feedbackSubmitCompletedMessage, Toast.LENGTH_LONG).show()
finish()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import com.duckduckgo.subscriptions.impl.feedback.SubscriptionFeedbackReportType
import com.duckduckgo.subscriptions.impl.feedback.SubscriptionFeedbackReportType.REQUEST_FEATURE
import com.duckduckgo.subscriptions.impl.feedback.SubscriptionFeedbackSubsSubCategory.ONE_TIME_PASSWORD
import com.duckduckgo.subscriptions.impl.feedback.SubscriptionFeedbackSubsSubCategory.OTHER
import com.duckduckgo.subscriptions.impl.feedback.SubscriptionFeedbackViewModel.Command.FeedbackCancelled
import com.duckduckgo.subscriptions.impl.feedback.SubscriptionFeedbackViewModel.Command.FeedbackCompleted
import com.duckduckgo.subscriptions.impl.feedback.SubscriptionFeedbackViewModel.Command.ShowHelpPages
import com.duckduckgo.subscriptions.impl.feedback.SubscriptionFeedbackViewModel.FeedbackFragmentState.FeedbackAction
Expand Down Expand Up @@ -300,69 +301,77 @@ class SubscriptionFeedbackViewModel @Inject constructor(
}
}

fun shouldGoBackInFeedbackFlow(): Boolean = viewState.value.previousFragmentState != null

fun handleBackInFlow() {
fun handleBackPress() {
viewModelScope.launch {
val newState = viewState.value.previousFragmentState
val currentFeedbackMetadata = viewState.value.feedbackMetadata
if (shouldGoBackInFeedbackFlow()) {
handleBackInFlow()
} else {
command.send(FeedbackCancelled)
}
}
}

if (newState != null) {
when (newState) {
is FeedbackGeneral -> ViewState(
feedbackMetadata = currentFeedbackMetadata.copy(
reportType = null,
),
currentFragmentState = newState,
previousFragmentState = null,
isForward = false,
)
private fun shouldGoBackInFeedbackFlow(): Boolean = viewState.value.previousFragmentState != null

is FeedbackAction -> ViewState(
feedbackMetadata = currentFeedbackMetadata.copy(
reportType = null,
),
currentFragmentState = newState,
previousFragmentState = if (currentFeedbackMetadata.source == DDG_SETTINGS) FeedbackGeneral else null,
isForward = false,
)
private suspend fun handleBackInFlow() {
val newState = viewState.value.previousFragmentState
val currentFeedbackMetadata = viewState.value.feedbackMetadata

is FeedbackCategory -> ViewState(
if (newState != null) {
when (newState) {
is FeedbackGeneral -> ViewState(
feedbackMetadata = currentFeedbackMetadata.copy(
reportType = null,
),
currentFragmentState = newState,
previousFragmentState = null,
isForward = false,
)

is FeedbackAction -> ViewState(
feedbackMetadata = currentFeedbackMetadata.copy(
reportType = null,
),
currentFragmentState = newState,
previousFragmentState = if (currentFeedbackMetadata.source == DDG_SETTINGS) FeedbackGeneral else null,
isForward = false,
)

is FeedbackCategory -> ViewState(
feedbackMetadata = currentFeedbackMetadata.copy(
category = null,
),
currentFragmentState = newState,
previousFragmentState = FeedbackAction,
isForward = false,
)

is FeedbackSubCategory -> {
val autoAssignedCategory = when (currentFeedbackMetadata.source) {
SUBSCRIPTION_SETTINGS, VPN_MANAGEMENT, VPN_EXCLUDED_APPS -> true
else -> false
}
val previousState =
if (currentFeedbackMetadata.reportType == REPORT_PROBLEM && autoAssignedCategory) {
FeedbackAction
} else {
FeedbackCategory(
currentFeedbackMetadata.reportType?.asTitle() ?: -1,
)
}
ViewState(
feedbackMetadata = currentFeedbackMetadata.copy(
category = null,
subCategory = null,
),
currentFragmentState = newState,
previousFragmentState = FeedbackAction,
previousFragmentState = previousState,
isForward = false,
)

is FeedbackSubCategory -> {
val autoAssignedCategory = when (currentFeedbackMetadata.source) {
SUBSCRIPTION_SETTINGS, VPN_MANAGEMENT, VPN_EXCLUDED_APPS -> true
else -> false
}
val previousState =
if (currentFeedbackMetadata.reportType == REPORT_PROBLEM && autoAssignedCategory) {
FeedbackAction
} else {
FeedbackCategory(
currentFeedbackMetadata.reportType?.asTitle() ?: -1,
)
}
ViewState(
feedbackMetadata = currentFeedbackMetadata.copy(
subCategory = null,
),
currentFragmentState = newState,
previousFragmentState = previousState,
isForward = false,
)
}

is FeedbackSubmit -> null // Not possible to go back to this page via back press
}?.also {
viewState.emit(it)
}

is FeedbackSubmit -> null // Not possible to go back to this page via back press
}?.also {
viewState.emit(it)
}
}
}
Expand Down Expand Up @@ -467,6 +476,7 @@ class SubscriptionFeedbackViewModel @Inject constructor(

sealed class Command {
data object FeedbackCompleted : Command()
data object FeedbackCancelled : Command()
data class ShowHelpPages(val url: String) : Command()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import com.duckduckgo.subscriptions.impl.feedback.SubscriptionFeedbackCategory.V
import com.duckduckgo.subscriptions.impl.feedback.SubscriptionFeedbackReportType.GENERAL_FEEDBACK
import com.duckduckgo.subscriptions.impl.feedback.SubscriptionFeedbackReportType.REPORT_PROBLEM
import com.duckduckgo.subscriptions.impl.feedback.SubscriptionFeedbackReportType.REQUEST_FEATURE
import com.duckduckgo.subscriptions.impl.feedback.SubscriptionFeedbackViewModel.Command.FeedbackCancelled
import com.duckduckgo.subscriptions.impl.feedback.SubscriptionFeedbackViewModel.Command.ShowHelpPages
import com.duckduckgo.subscriptions.impl.feedback.SubscriptionFeedbackViewModel.FeedbackFragmentState.FeedbackAction
import com.duckduckgo.subscriptions.impl.feedback.SubscriptionFeedbackViewModel.FeedbackFragmentState.FeedbackCategory
Expand Down Expand Up @@ -557,7 +558,7 @@ class SubscriptionFeedbackViewModelTest {
viewModel.allowUserToChooseFeedbackType() // Show General
viewModel.onProFeedbackSelected() // Show Action

viewModel.handleBackInFlow()
viewModel.handleBackPress()

expectMostRecentItem().assertViewStateMoveBack(
expectedPreviousFragmentState = null,
Expand All @@ -575,7 +576,7 @@ class SubscriptionFeedbackViewModelTest {
viewModel.allowUserToChooseReportType(source = SUBSCRIPTION_SETTINGS) // Show action
viewModel.onReportTypeSelected(REQUEST_FEATURE) // Show submit

viewModel.handleBackInFlow()
viewModel.handleBackPress()

expectMostRecentItem().assertViewStateMoveBack(
expectedPreviousFragmentState = null,
Expand All @@ -593,7 +594,7 @@ class SubscriptionFeedbackViewModelTest {
viewModel.allowUserToChooseReportType(source = SUBSCRIPTION_SETTINGS) // Show action
viewModel.onReportTypeSelected(GENERAL_FEEDBACK) // Show submit

viewModel.handleBackInFlow()
viewModel.handleBackPress()

expectMostRecentItem().assertViewStateMoveBack(
expectedPreviousFragmentState = null,
Expand All @@ -611,7 +612,7 @@ class SubscriptionFeedbackViewModelTest {
viewModel.allowUserToChooseReportType(source = SUBSCRIPTION_SETTINGS) // Show action
viewModel.onReportTypeSelected(REPORT_PROBLEM) // Show subcategory

viewModel.handleBackInFlow()
viewModel.handleBackPress()

expectMostRecentItem().assertViewStateMoveBack(
expectedPreviousFragmentState = null,
Expand All @@ -630,7 +631,7 @@ class SubscriptionFeedbackViewModelTest {
viewModel.allowUserToChooseReportType(source = VPN_MANAGEMENT) // Show action
viewModel.onReportTypeSelected(REPORT_PROBLEM) // Show subcategory

viewModel.handleBackInFlow()
viewModel.handleBackPress()

expectMostRecentItem().assertViewStateMoveBack(
expectedPreviousFragmentState = null,
Expand All @@ -650,7 +651,7 @@ class SubscriptionFeedbackViewModelTest {
viewModel.onProFeedbackSelected() // show action
viewModel.onReportTypeSelected(REPORT_PROBLEM) // Show category

viewModel.handleBackInFlow()
viewModel.handleBackPress()

expectMostRecentItem().assertViewStateMoveBack(
expectedPreviousFragmentState = FeedbackGeneral,
Expand All @@ -670,7 +671,7 @@ class SubscriptionFeedbackViewModelTest {
viewModel.onReportTypeSelected(REPORT_PROBLEM) // Show category
viewModel.onCategorySelected(VPN) // Show subcategory

viewModel.handleBackInFlow()
viewModel.handleBackPress()

expectMostRecentItem().assertViewStateMoveBack(
expectedPreviousFragmentState = FeedbackAction,
Expand All @@ -691,7 +692,7 @@ class SubscriptionFeedbackViewModelTest {
viewModel.onReportTypeSelected(REPORT_PROBLEM) // Show category
viewModel.onCategorySelected(SUBS_AND_PAYMENTS) // Show subcategory

viewModel.handleBackInFlow()
viewModel.handleBackPress()

expectMostRecentItem().assertViewStateMoveBack(
expectedPreviousFragmentState = FeedbackAction,
Expand All @@ -712,7 +713,7 @@ class SubscriptionFeedbackViewModelTest {
viewModel.onReportTypeSelected(REPORT_PROBLEM) // Show category
viewModel.onCategorySelected(PIR) // Show subcategory

viewModel.handleBackInFlow()
viewModel.handleBackPress()

expectMostRecentItem().assertViewStateMoveBack(
expectedPreviousFragmentState = FeedbackAction,
Expand All @@ -733,7 +734,7 @@ class SubscriptionFeedbackViewModelTest {
viewModel.onReportTypeSelected(REPORT_PROBLEM) // Show category
viewModel.onCategorySelected(ITR) // Show subcategory

viewModel.handleBackInFlow()
viewModel.handleBackPress()

expectMostRecentItem().assertViewStateMoveBack(
expectedPreviousFragmentState = FeedbackAction,
Expand All @@ -755,7 +756,7 @@ class SubscriptionFeedbackViewModelTest {
viewModel.onCategorySelected(SUBS_AND_PAYMENTS) // Show subcategory
viewModel.onSubcategorySelected(SubscriptionFeedbackSubsSubCategory.ONE_TIME_PASSWORD) // Show submit

viewModel.handleBackInFlow()
viewModel.handleBackPress()

expectMostRecentItem().assertViewStateMoveBack(
expectedPreviousFragmentState = FeedbackCategory(R.string.feedbackActionReportIssue),
Expand All @@ -776,7 +777,7 @@ class SubscriptionFeedbackViewModelTest {
viewModel.onReportTypeSelected(REPORT_PROBLEM) // Show subcategory
viewModel.onSubcategorySelected(BROWSER_CRASH_FREEZE) // Show submit

viewModel.handleBackInFlow()
viewModel.handleBackPress()

expectMostRecentItem().assertViewStateMoveBack(
expectedPreviousFragmentState = FeedbackAction,
Expand All @@ -797,7 +798,7 @@ class SubscriptionFeedbackViewModelTest {
viewModel.onReportTypeSelected(REPORT_PROBLEM) // Show subcategory
viewModel.onSubcategorySelected(SubscriptionFeedbackSubsSubCategory.ONE_TIME_PASSWORD) // Show submit

viewModel.handleBackInFlow()
viewModel.handleBackPress()

expectMostRecentItem().assertViewStateMoveBack(
expectedPreviousFragmentState = FeedbackAction,
Expand All @@ -811,6 +812,17 @@ class SubscriptionFeedbackViewModelTest {
}
}

@Test
fun whenUserIsInFirstPageWhenBackIsPressedThenEmitCancelledCommand() = runTest {
viewModel.allowUserToChooseReportType(source = SUBSCRIPTION_SETTINGS) // Show action

viewModel.handleBackPress()

viewModel.commands().test {
assertEquals(FeedbackCancelled, expectMostRecentItem())
}
}

@Test
fun whenFeatureRequestSubmittedTheSendFeatureRequestPixel() = runTest {
viewModel.allowUserToChooseFeedbackType() // Show general
Expand Down

0 comments on commit e408922

Please sign in to comment.