2
0
mirror of https://github.com/fork-maintainers/iceraven-browser synced 2024-11-19 09:25:34 +00:00

[fenix] For https://github.com/mozilla-mobile/fenix/issues/12801 - Extra debug menu trigger, disable if already triggered

This commit is contained in:
Tiger Oakes 2020-07-21 15:12:37 -07:00 committed by Mihai Branescu
parent 1df7dce5d0
commit fb7c801b38
3 changed files with 190 additions and 41 deletions

View File

@ -10,13 +10,11 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.core.content.pm.PackageInfoCompat
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.DividerItemDecoration
import com.google.android.gms.oss.licenses.OssLicensesMenuActivity
import kotlinx.android.synthetic.main.fragment_about.*
import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.BuildConfig
import org.mozilla.fenix.HomeActivity
@ -39,10 +37,9 @@ import org.mozilla.geckoview.BuildConfig as GeckoViewBuildConfig
* Displays the logo and information about the app, including library versions.
*/
class AboutFragment : Fragment(), AboutPageListener {
private lateinit var appName: String
private val aboutPageAdapter: AboutPageAdapter = AboutPageAdapter(this)
private var secretDebugMenuClicks = 0
private var lastDebugMenuToast: Toast? = null
override fun onCreateView(
inflater: LayoutInflater,
@ -56,15 +53,7 @@ class AboutFragment : Fragment(), AboutPageListener {
return rootView
}
override fun onResume() {
super.onResume()
secretDebugMenuClicks = 0
}
@ExperimentalCoroutinesApi
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
about_list.run {
adapter = aboutPageAdapter
addItemDecoration(
@ -75,33 +64,10 @@ class AboutFragment : Fragment(), AboutPageListener {
)
}
// 5 taps on the logo activate the "secret" debug menu.
wordmark.setOnClickListener {
// Because the user will mostly likely tap the logo in rapid succession,
// we ensure only 1 toast is shown at any given time.
lastDebugMenuToast?.let { toast -> toast.cancel() }
secretDebugMenuClicks += 1
when (secretDebugMenuClicks) {
in 2 until SECRET_DEBUG_MENU_CLICKS -> {
val clicksLeft = SECRET_DEBUG_MENU_CLICKS - secretDebugMenuClicks
val toast = Toast.makeText(
context,
getString(R.string.about_debug_menu_toast_progress, clicksLeft),
Toast.LENGTH_SHORT
)
toast.show()
lastDebugMenuToast = toast
}
SECRET_DEBUG_MENU_CLICKS -> {
Toast.makeText(
context,
getString(R.string.about_debug_menu_toast_done),
Toast.LENGTH_LONG
).show()
requireContext().settings().showSecretDebugMenuThisSession = true
}
}
}
lifecycle.addObserver(SecretDebugMenuTrigger(
logoView = wordmark,
settings = view.context.settings()
))
populateAboutHeader()
aboutPageAdapter.submitList(populateAboutList())
@ -233,7 +199,5 @@ class AboutFragment : Fragment(), AboutPageListener {
companion object {
private const val ABOUT_LICENSE_URL = "about:license"
// Number of clicks on the app logo to enable the "secret" debug menu.
private const val SECRET_DEBUG_MENU_CLICKS = 5
}
}

View File

@ -0,0 +1,71 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.settings.about
import android.view.View
import android.widget.Toast
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import org.mozilla.fenix.R
import org.mozilla.fenix.utils.Settings
/**
* Triggers the "secret" debug menu when logoView is tapped 5 times.
*/
class SecretDebugMenuTrigger(
logoView: View,
private val settings: Settings
) : View.OnClickListener, LifecycleObserver {
private var secretDebugMenuClicks = 0
private var lastDebugMenuToast: Toast? = null
init {
if (!settings.showSecretDebugMenuThisSession) {
logoView.setOnClickListener(this)
}
}
/**
* Reset the [secretDebugMenuClicks] counter.
*/
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun clearClickCounter() {
secretDebugMenuClicks = 0
}
override fun onClick(v: View) {
// Because the user will mostly likely tap the logo in rapid succession,
// we ensure only 1 toast is shown at any given time.
lastDebugMenuToast?.cancel()
secretDebugMenuClicks += 1
when (secretDebugMenuClicks) {
in 2 until SECRET_DEBUG_MENU_CLICKS -> {
val clicksLeft = SECRET_DEBUG_MENU_CLICKS - secretDebugMenuClicks
val toast = Toast.makeText(
v.context,
v.context.getString(R.string.about_debug_menu_toast_progress, clicksLeft),
Toast.LENGTH_SHORT
)
toast.show()
lastDebugMenuToast = toast
}
SECRET_DEBUG_MENU_CLICKS -> {
Toast.makeText(
v.context,
R.string.about_debug_menu_toast_done,
Toast.LENGTH_LONG
).show()
settings.showSecretDebugMenuThisSession = true
}
}
}
companion object {
// Number of clicks on the app logo to enable the "secret" debug menu.
private const val SECRET_DEBUG_MENU_CLICKS = 5
}
}

View File

@ -0,0 +1,114 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.settings.about
import android.content.Context
import android.view.View
import android.widget.Toast
import io.mockk.CapturingSlot
import io.mockk.MockKAnnotations
import io.mockk.Runs
import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.just
import io.mockk.mockkStatic
import io.mockk.slot
import io.mockk.unmockkStatic
import io.mockk.verify
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.mozilla.fenix.R
import org.mozilla.fenix.utils.Settings
class SecretDebugMenuTriggerTest {
@MockK private lateinit var logoView: View
@MockK private lateinit var context: Context
@MockK private lateinit var settings: Settings
@MockK(relaxUnitFun = true) private lateinit var toast: Toast
private lateinit var clickListener: CapturingSlot<View.OnClickListener>
@Before
fun setup() {
MockKAnnotations.init(this)
mockkStatic(Toast::class)
clickListener = slot()
every { logoView.setOnClickListener(capture(clickListener)) } just Runs
every { logoView.context } returns context
every {
context.getString(R.string.about_debug_menu_toast_progress, any())
} returns "Debug menu: x click(s) left to enable"
every { settings.showSecretDebugMenuThisSession } returns false
every { settings.showSecretDebugMenuThisSession = any() } just Runs
every { Toast.makeText(context, any<Int>(), any()) } returns toast
every { Toast.makeText(context, any<String>(), any()) } returns toast
}
@After
fun teardown() {
unmockkStatic(Toast::class)
}
@Test
fun `toast is not displayed on first click`() {
SecretDebugMenuTrigger(logoView, settings)
clickListener.captured.onClick(logoView)
verify(inverse = true) { Toast.makeText(context, any<String>(), any()) }
verify(inverse = true) { toast.show() }
}
@Test
fun `toast is displayed on second click`() {
SecretDebugMenuTrigger(logoView, settings)
clickListener.captured.onClick(logoView)
clickListener.captured.onClick(logoView)
verify { context.getString(R.string.about_debug_menu_toast_progress, 3) }
verify { Toast.makeText(context, any<String>(), Toast.LENGTH_SHORT) }
verify { toast.show() }
}
@Test
fun `clearClickCounter resets counter`() {
val trigger = SecretDebugMenuTrigger(logoView, settings)
clickListener.captured.onClick(logoView)
trigger.clearClickCounter()
clickListener.captured.onClick(logoView)
verify(inverse = true) { Toast.makeText(context, any<String>(), any()) }
verify(inverse = true) { toast.show() }
}
@Test
fun `toast is displayed on fifth click`() {
SecretDebugMenuTrigger(logoView, settings)
clickListener.captured.onClick(logoView)
clickListener.captured.onClick(logoView)
clickListener.captured.onClick(logoView)
clickListener.captured.onClick(logoView)
clickListener.captured.onClick(logoView)
verify { Toast.makeText(
context,
R.string.about_debug_menu_toast_done,
Toast.LENGTH_LONG
) }
verify { toast.show() }
verify { settings.showSecretDebugMenuThisSession = true }
}
@Test
fun `don't register click listener if menu is already shown`() {
every { settings.showSecretDebugMenuThisSession } returns true
SecretDebugMenuTrigger(logoView, settings)
verify(inverse = true) { logoView.setOnClickListener(any()) }
}
}