Skip to content

Commit

Permalink
Fix UI flash after fire button action (#4910)
Browse files Browse the repository at this point in the history
Task/Issue URL:
https://app.asana.com/0/488551667048375/1207509101295228/f

### Description

- Fixes the flash of the website when pressing the “Clear All Tabs and
Data” button. We had a fading transition for the FireActivity and this
seemed to allow the user to see the website before we restart the app
process. We now do not specifically apply a transition to the
FireActivity when clicking the “Clear All Tabs and Data” button, leaving
a black background that integrates well with the Fire animation.
- Fixes the navigation buttons being harder to see on older API
versions. We set the navigation bar to black and therfore the buttons
were not visible. We now go edge to edge and let the system decide how
to overlay the navigation bar
- Fix the clipping of the Fire animation. The Fire animation would start
above the navigation bar and then stop at the status bar which didn’t
look very good. I believe once upon a time this worked but it’s now
clipping. This fixes that and ensures the animation starts underneath
the navigation bar and does not clip when reaching the status bar.

### Steps to test this PR

_UI Flash_

Worth noting that I seemed to see the website flash after the first
clear data attempt from app launch. In subsequent clear data attempts I
did not see the website.

- [x] Open app fresh (ensure it’s been force closed before opening)
- [x] Navigate to a webpage
- [x] Press the fire button
- [x] Press “Clear All Tabs and Data"
- [x] Ensure you do not see the webpage after the fire animation has
played

_Edge to Edge Fire Animation_

- [x] Open app 
- [x] Press the fire button
- [x] Press “Clear All Tabs and Data"
- [x] Ensure the flame (or whatever animation you have chosen) starts
underneath the navigation bar and moves under the status bar without
being clipped

### UI changes

#### Fixing UI Flash

| Before | After |
|--------|-------|
| <video
src="https://github.com/user-attachments/assets/a7d7137a-3583-4b04-8224-eb353662006a"
width="400px"></video> (API 34 Before) | <video
src="https://github.com/user-attachments/assets/eac3fe11-426e-49fa-a2db-6dd5b025263e"
width="400px"></video> (API 34 After) |

#### Edge to Edge Fire animation

| Before | After |
|--------|-------|
| <video
src="https://github.com/user-attachments/assets/4a8c64a8-6c6c-48cf-a640-68154d813d3e"
width="400px"></video> (API 26 Before) | <video
src="https://github.com/user-attachments/assets/ab72d8b6-484c-4a16-b85f-9f2bf186a6fc"
width="400px"></video> (API 26) |
| | <video
src="https://github.com/user-attachments/assets/ea6f5290-8ec7-4d90-a87b-042f875d2ad7"
width="400px"></video> (API 27) |
| | <video
src="https://github.com/user-attachments/assets/717bf4da-db31-4111-9d78-cd5bfd461c8e"
width="400px"></video> (API 28) |
| | <video
src="https://github.com/user-attachments/assets/2ed7e978-a948-46d8-8b51-eb9c0e9179e8"
width="400px"></video> (API 29) |
| | <video
src="https://github.com/user-attachments/assets/20e04c96-89dc-4927-8d07-a025c279787e"
width="400px"></video> (API 29 Dark) |
| <video
src="https://github.com/user-attachments/assets/b57323ba-6f4e-48d8-b5fc-f053a76809c8"
width="400px"></video> (OnePlus 30 Light Before) | <video
src="https://github.com/user-attachments/assets/a86b4012-fb3e-4b8b-8adf-bf92dab6b784"
width="400px"></video> (OnePlus 30 Light) |
| <video
src="https://github.com/user-attachments/assets/2223d17c-63be-4412-a333-c9c4f27319f6"
width="400px"></video> (OnePlus 30 Dark Before) | <video
src="https://github.com/user-attachments/assets/148d439c-bba8-488f-b2c0-89e4cb704502"
width="400px"></video> (OnePlus 30 Dark) |
| | <video
src="https://github.com/user-attachments/assets/27c2fb17-c88b-4bbc-8e72-fbad1c79fafd"
width="400px"></video> (API 31) |
| | <video
src="https://github.com/user-attachments/assets/58810067-8250-44c6-82aa-d41e1eab908a"
width="400px"></video> (API 32 Dark) |
| | <video
src="https://github.com/user-attachments/assets/e17aea70-7ac6-4268-87d1-0e0081089c57"
width="400px"></video> (API 33) |
| | <video
src="https://github.com/user-attachments/assets/e8e6817e-10da-48a4-871f-be78e6aa53e4"
width="400px"></video> (API 33 Light) |
| | <video
src="https://github.com/user-attachments/assets/43dde46e-bbd8-4eca-9e21-b27cb5edba7b"
width="400px"></video> (API 34 No Animation Selected) |
| | <video
src="https://github.com/user-attachments/assets/f6dc318a-4f0c-4d87-803e-83181b2ea49e"
width="400px"></video> (API 34 Airstream) |
| <video
src="https://github.com/user-attachments/assets/52f677cc-644d-465d-b66c-e291972289d5"
width="400px"></video> (API 34 Three Button Before) | <video
src="https://github.com/user-attachments/assets/aa2cc061-9753-494c-8b9d-21ddeafce7fd"
width="400px"></video> (API 34 Three Button) |
| | <video
src="https://github.com/user-attachments/assets/2b06caec-d4d9-424a-8c02-ec411af803ee"
width="400px"></video> (API 34 Dark Three Button) |
| <video
src="https://github.com/user-attachments/assets/bcdc6127-ebab-487f-888c-b3f3ff621963"
width="400px"></video> (API 34 Dark Before) | <video
src="https://github.com/user-attachments/assets/ebb95dd6-41a3-49db-91d4-13140d94b2b9"
width="400px"></video> (API 34 Dark) |
| <video
src="https://github.com/user-attachments/assets/b1d7eaff-8341-47bd-986b-e8b987a23a74"
width="400px"></video> (API 34 Light Before) | <video
src="https://github.com/user-attachments/assets/2191d12d-0f7d-41c0-b71c-b6d5c60a9f8e"
width="400px"></video> (API 34 Light) |
  • Loading branch information
mikescamell authored Aug 22, 2024
1 parent cb783fe commit 1458d21
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import com.duckduckgo.app.settings.db.SettingsDataStore
import com.duckduckgo.app.sitepermissions.SitePermissionsActivity
import com.duckduckgo.app.statistics.pixels.Pixel
import com.duckduckgo.app.tabs.model.TabEntity
import com.duckduckgo.appbuildconfig.api.AppBuildConfig
import com.duckduckgo.autofill.api.emailprotection.EmailProtectionLinkVerifier
import com.duckduckgo.browser.api.ui.BrowserScreens.BookmarksScreenNoParams
import com.duckduckgo.common.ui.DuckDuckGoActivity
Expand Down Expand Up @@ -122,6 +123,9 @@ open class BrowserActivity : DuckDuckGoActivity() {
@Inject
lateinit var fireButtonStore: FireButtonStore

@Inject
lateinit var appBuildConfig: AppBuildConfig

private val lastActiveTabs = TabList()

private var currentTab: BrowserTabFragment? = null
Expand Down Expand Up @@ -447,6 +451,7 @@ open class BrowserActivity : DuckDuckGoActivity() {
appCoroutineScope = appCoroutineScope,
dispatcherProvider = dispatcherProvider,
fireButtonStore = fireButtonStore,
appBuildConfig = appBuildConfig,
)
dialog.clearStarted = {
removeObservers()
Expand Down
19 changes: 11 additions & 8 deletions app/src/main/java/com/duckduckgo/app/fire/FireActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import androidx.appcompat.app.AppCompatActivity
import com.duckduckgo.anvil.annotations.InjectWith
import com.duckduckgo.app.browser.BrowserActivity
import com.duckduckgo.app.global.view.fadeTransitionConfig
import com.duckduckgo.app.global.view.noAnimationConfig
import com.duckduckgo.di.scopes.ActivityScope

/**
Expand Down Expand Up @@ -53,19 +54,21 @@ class FireActivity : AppCompatActivity() {
fun triggerRestart(
context: Context,
notifyDataCleared: Boolean,
) {
triggerRestart(context, getRestartIntent(context, notifyDataCleared))
}

private fun triggerRestart(
context: Context,
nextIntent: Intent,
enableTransitionAnimation: Boolean = true,
) {
val intent = Intent(context, FireActivity::class.java)
val nextIntent = getRestartIntent(context, notifyDataCleared)

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.putExtra(KEY_RESTART_INTENTS, nextIntent)

context.startActivity(intent, context.fadeTransitionConfig())
val transitionAnimationConfig = if (enableTransitionAnimation) {
context.fadeTransitionConfig()
} else {
context.noAnimationConfig()
}

context.startActivity(intent, transitionAnimationConfig)
if (context is Activity) {
context.overridePendingTransition(0, 0)
context.finish()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ fun Context.fadeTransitionConfig(): Bundle? {
return config.toBundle()
}

fun Context.noAnimationConfig(): Bundle? =
ActivityOptionsCompat.makeCustomAnimation(this, 0, 0).toBundle()

fun FragmentActivity.toggleFullScreen() {
if (isFullScreen()) {
// If we are exiting full screen, reset the orientation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ interface ClearDataAction {

suspend fun setAppUsedSinceLastClearFlag(appUsedSinceLastClear: Boolean)
fun killProcess()
fun killAndRestartProcess(notifyDataCleared: Boolean)
fun killAndRestartProcess(notifyDataCleared: Boolean, enableTransitionAnimation: Boolean = true)
}

class ClearPersonalDataAction(
Expand All @@ -77,9 +77,9 @@ class ClearPersonalDataAction(
private val dispatchers: DispatcherProvider = DefaultDispatcherProvider(),
) : ClearDataAction {

override fun killAndRestartProcess(notifyDataCleared: Boolean) {
override fun killAndRestartProcess(notifyDataCleared: Boolean, enableTransitionAnimation: Boolean) {
Timber.i("Restarting process")
FireActivity.triggerRestart(context, notifyDataCleared)
FireActivity.triggerRestart(context, notifyDataCleared, enableTransitionAnimation)
}

override fun killProcess() {
Expand Down
56 changes: 49 additions & 7 deletions app/src/main/java/com/duckduckgo/app/global/view/FireDialog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,37 @@ import android.animation.Animator
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.provider.Settings.Global.ANIMATOR_DURATION_SCALE
import android.view.LayoutInflater
import androidx.core.content.ContextCompat
import android.view.View
import android.view.WindowManager
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat.Type
import androidx.core.view.WindowInsetsControllerCompat
import androidx.core.view.updatePadding
import com.airbnb.lottie.RenderMode
import com.duckduckgo.app.browser.databinding.SheetFireClearDataBinding
import com.duckduckgo.app.firebutton.FireButtonStore
import com.duckduckgo.app.global.events.db.UserEventKey
import com.duckduckgo.app.global.events.db.UserEventsStore
import com.duckduckgo.app.global.view.FireDialog.FireDialogClearAllEvent.AnimationFinished
import com.duckduckgo.app.global.view.FireDialog.FireDialogClearAllEvent.ClearAllDataFinished
import com.duckduckgo.app.pixels.AppPixelName.*
import com.duckduckgo.app.pixels.AppPixelName.FIRE_DIALOG_ANIMATION
import com.duckduckgo.app.pixels.AppPixelName.FIRE_DIALOG_CLEAR_PRESSED
import com.duckduckgo.app.settings.clear.getPixelValue
import com.duckduckgo.app.settings.db.SettingsDataStore
import com.duckduckgo.app.statistics.pixels.Pixel
import com.duckduckgo.app.statistics.pixels.Pixel.PixelParameter.FIRE_ANIMATION
import com.duckduckgo.appbuildconfig.api.AppBuildConfig
import com.duckduckgo.common.ui.view.gone
import com.duckduckgo.common.ui.view.setAndPropagateUpFitsSystemWindows
import com.duckduckgo.common.ui.view.show
import com.duckduckgo.common.utils.DispatcherProvider
import com.duckduckgo.mobile.android.R as CommonR
import com.google.android.material.R as MaterialR
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import kotlinx.coroutines.CoroutineScope
Expand All @@ -60,7 +69,8 @@ class FireDialog(
private val appCoroutineScope: CoroutineScope,
private val dispatcherProvider: DispatcherProvider,
private val fireButtonStore: FireButtonStore,
) : BottomSheetDialog(context, com.duckduckgo.mobile.android.R.style.Widget_DuckDuckGo_FireDialog) {
private val appBuildConfig: AppBuildConfig,
) : BottomSheetDialog(context, CommonR.style.Widget_DuckDuckGo_FireDialog) {

private lateinit var binding: SheetFireClearDataBinding

Expand Down Expand Up @@ -93,12 +103,39 @@ class FireDialog(
cancel()
}

if (appBuildConfig.sdkInt == Build.VERSION_CODES.O) {
window?.navigationBarColor = context.resources.getColor(CommonR.color.translucentDark, null)
} else if (appBuildConfig.sdkInt > Build.VERSION_CODES.O && appBuildConfig.sdkInt < Build.VERSION_CODES.R) {
window?.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
}

removeTopPadding()
addBottomPaddingToButtons()

if (animationEnabled()) {
configureFireAnimationView()
}
behavior.state = BottomSheetBehavior.STATE_EXPANDED
}

private fun removeTopPadding() {
findViewById<View>(MaterialR.id.design_bottom_sheet)?.apply {
ViewCompat.setOnApplyWindowInsetsListener(this) { view, insets ->
view.updatePadding(top = 0)
insets
}
}
}

private fun addBottomPaddingToButtons() {
binding.fireDialogRootView.apply {
ViewCompat.setOnApplyWindowInsetsListener(this) { view, insets ->
view.updatePadding(bottom = insets.getInsets(Type.systemBars()).bottom)
insets
}
}
}

private fun configureFireAnimationView() {
binding.fireAnimationView.setAnimation(settingsDataStore.selectedFireAnimation.resId)
/**
Expand Down Expand Up @@ -139,7 +176,12 @@ class FireDialog(
}

private fun playAnimation() {
window?.navigationBarColor = ContextCompat.getColor(context, CommonR.color.black)
window?.apply {
WindowInsetsControllerCompat(this, binding.root).apply {
isAppearanceLightStatusBars = false
isAppearanceLightNavigationBars = false
}
}
setCancelable(false)
setCanceledOnTouchOutside(false)
binding.fireAnimationView.show()
Expand Down Expand Up @@ -174,12 +216,12 @@ class FireDialog(
binding.fireAnimationView.addAnimatorUpdateListener(accelerateAnimatorUpdateListener)
}
} else {
clearPersonalDataAction.killAndRestartProcess(notifyDataCleared = false)
clearPersonalDataAction.killAndRestartProcess(notifyDataCleared = false, enableTransitionAnimation = false)
}
}

private sealed class FireDialogClearAllEvent {
object AnimationFinished : FireDialogClearAllEvent()
object ClearAllDataFinished : FireDialogClearAllEvent()
data object AnimationFinished : FireDialogClearAllEvent()
data object ClearAllDataFinished : FireDialogClearAllEvent()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import android.animation.ValueAnimator
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.core.content.IntentCompat
import com.airbnb.lottie.LottieAnimationView
import com.airbnb.lottie.RenderMode
import com.duckduckgo.anvil.annotations.InjectWith
Expand All @@ -42,7 +43,7 @@ class FireAnimationActivity : DuckDuckGoActivity() {
super.onCreate(savedInstanceState)
setContentView(binding.root)

val fireAnimationSerializable = intent.getSerializableExtra(FIRE_ANIMATION_EXTRA)
val fireAnimationSerializable = IntentCompat.getSerializableExtra(intent, FIRE_ANIMATION_EXTRA, FireAnimation::class.java)

if (fireAnimationSerializable == null) finish()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import com.duckduckgo.app.tabs.model.TabSwitcherData.LayoutType
import com.duckduckgo.app.tabs.ui.TabSwitcherViewModel.Command
import com.duckduckgo.app.tabs.ui.TabSwitcherViewModel.Command.Close
import com.duckduckgo.app.tabs.ui.TabSwitcherViewModel.Command.CloseAllTabsRequest
import com.duckduckgo.appbuildconfig.api.AppBuildConfig
import com.duckduckgo.common.ui.DuckDuckGoActivity
import com.duckduckgo.common.ui.view.dialog.TextAlertDialogBuilder
import com.duckduckgo.common.ui.view.gone
Expand Down Expand Up @@ -109,6 +110,9 @@ class TabSwitcherActivity : DuckDuckGoActivity(), TabSwitcherListener, Coroutine
@Inject
lateinit var fireButtonStore: FireButtonStore

@Inject
lateinit var appBuildConfig: AppBuildConfig

private val viewModel: TabSwitcherViewModel by bindViewModel()

private val tabsAdapter: TabSwitcherAdapter by lazy { TabSwitcherAdapter(this, webViewPreviewPersister, this, faviconManager) }
Expand Down Expand Up @@ -383,6 +387,7 @@ class TabSwitcherActivity : DuckDuckGoActivity(), TabSwitcherListener, Coroutine
appCoroutineScope = appCoroutineScope,
dispatcherProvider = dispatcherProvider,
fireButtonStore = fireButtonStore,
appBuildConfig = appBuildConfig,
)
dialog.show()
}
Expand Down
40 changes: 17 additions & 23 deletions app/src/main/res/layout/sheet_fire_clear_data.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,35 +27,29 @@
android:visibility="gone"
app:lottie_loop="false" />

<FrameLayout
<LinearLayout
android:id="@+id/fireDialogRootView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom">
android:background="@drawable/rounded_top_corners_bottom_sheet_background"
android:orientation="vertical"
android:paddingTop="@dimen/actionBottomSheetVerticalPadding"
android:paddingBottom="@dimen/actionBottomSheetVerticalPadding">

<LinearLayout
<com.duckduckgo.common.ui.view.listitem.OneLineListItem
android:id="@+id/clearAllOption"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/rounded_top_corners_bottom_sheet_background"
android:orientation="vertical"
android:paddingTop="@dimen/actionBottomSheetVerticalPadding"
android:paddingBottom="@dimen/actionBottomSheetVerticalPadding">
app:leadingIcon="@drawable/ic_fire_red"
app:primaryText="@string/fireClearAll"
app:primaryTextColorOverlay="?attr/daxColorDestructive" />

<com.duckduckgo.common.ui.view.listitem.OneLineListItem
android:id="@+id/clearAllOption"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:leadingIcon="@drawable/ic_fire_red"
app:primaryText="@string/fireClearAll"
app:primaryTextColorOverlay="?attr/daxColorDestructive" />

<com.duckduckgo.common.ui.view.listitem.OneLineListItem
android:id="@+id/cancelOption"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:leadingIcon="@drawable/ic_close_24"
app:primaryText="@string/fireCancel" />
<com.duckduckgo.common.ui.view.listitem.OneLineListItem
android:id="@+id/cancelOption"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:leadingIcon="@drawable/ic_close_24"
app:primaryText="@string/fireCancel" />

</LinearLayout>
</FrameLayout>
</LinearLayout>
</FrameLayout>
3 changes: 3 additions & 0 deletions common/common-ui/src/main/res/values/widgets.xml
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,9 @@
<style name="Widget.DuckDuckGo.FireDialog" parent="@style/Theme.Design.BottomSheetDialog">
<item name="android:windowIsFloating">false</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="enableEdgeToEdge">true</item>
<item name="android:enforceNavigationBarContrast" tools:targetApi="q">false</item>
<item name="bottomSheetStyle">@style/Widget.DuckDuckGo.FireDialogStyle</item>
</style>

Expand Down

0 comments on commit 1458d21

Please sign in to comment.