1
0
Fork 0

For #3360 - Adds empty state for TP Exceptions

master
Emily Kager 2019-07-18 15:15:24 -07:00 committed by Emily Kager
parent 7588251f8b
commit 9b5baa2358
9 changed files with 116 additions and 32 deletions

View File

@ -35,6 +35,7 @@ import mozilla.components.support.utils.SafeIntent
import org.mozilla.fenix.components.FenixSnackbar
import org.mozilla.fenix.components.isSentryEnabled
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.exceptions.ExceptionsFragmentDirections
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.getRootView
import org.mozilla.fenix.ext.nav
@ -230,15 +231,21 @@ open class HomeActivity : AppCompatActivity(), ShareFragment.TabsSharedCallback
}
BrowserDirection.FromSearch -> {
fragmentId = R.id.searchFragment
SearchFragmentDirections.actionSearchFragmentToBrowserFragment(customTabSessionId)
SearchFragmentDirections.actionSearchFragmentToBrowserFragment(
customTabSessionId
)
}
BrowserDirection.FromSettings -> {
fragmentId = R.id.settingsFragment
SettingsFragmentDirections.actionSettingsFragmentToBrowserFragment(customTabSessionId)
SettingsFragmentDirections.actionSettingsFragmentToBrowserFragment(
customTabSessionId
)
}
BrowserDirection.FromBookmarks -> {
fragmentId = R.id.bookmarkFragment
BookmarkFragmentDirections.actionBookmarkFragmentToBrowserFragment(customTabSessionId)
BookmarkFragmentDirections.actionBookmarkFragmentToBrowserFragment(
customTabSessionId
)
}
BrowserDirection.FromBookmarksFolderSelect -> {
fragmentId = R.id.bookmarkSelectFolderFragment
@ -247,7 +254,9 @@ open class HomeActivity : AppCompatActivity(), ShareFragment.TabsSharedCallback
}
BrowserDirection.FromHistory -> {
fragmentId = R.id.historyFragment
HistoryFragmentDirections.actionHistoryFragmentToBrowserFragment(customTabSessionId)
HistoryFragmentDirections.actionHistoryFragmentToBrowserFragment(
customTabSessionId
)
}
}
} else {
@ -259,7 +268,12 @@ open class HomeActivity : AppCompatActivity(), ShareFragment.TabsSharedCallback
}
}
private fun load(searchTermOrURL: String, newTab: Boolean, engine: SearchEngine?, forceSearch: Boolean) {
private fun load(
searchTermOrURL: String,
newTab: Boolean,
engine: SearchEngine?,
forceSearch: Boolean
) {
val isPrivate = this.browsingModeManager.isPrivate
val loadUrlUseCase = if (newTab) {
@ -273,7 +287,13 @@ open class HomeActivity : AppCompatActivity(), ShareFragment.TabsSharedCallback
val searchUseCase: (String) -> Unit = { searchTerms ->
if (newTab) {
components.useCases.searchUseCases.newTabSearch
.invoke(searchTerms, Session.Source.USER_ENTERED, true, isPrivate, searchEngine = engine)
.invoke(
searchTerms,
Session.Source.USER_ENTERED,
true,
isPrivate,
searchEngine = engine
)
} else components.useCases.searchUseCases.defaultSearch.invoke(searchTerms, engine)
}
@ -377,5 +397,5 @@ open class HomeActivity : AppCompatActivity(), ShareFragment.TabsSharedCallback
enum class BrowserDirection {
FromGlobal, FromHome, FromSearch, FromSettings, FromBookmarks,
FromBookmarksFolderSelect, FromHistory
FromBookmarksFolderSelect, FromHistory, FromExceptions
}

View File

@ -5,13 +5,13 @@
package org.mozilla.fenix.exceptions
import android.view.ViewGroup
import org.mozilla.fenix.mvi.ViewState
import org.mozilla.fenix.mvi.Change
import org.mozilla.fenix.mvi.Action
import org.mozilla.fenix.mvi.ActionBusFactory
import org.mozilla.fenix.mvi.Change
import org.mozilla.fenix.mvi.UIComponent
import org.mozilla.fenix.mvi.UIComponentViewModelBase
import org.mozilla.fenix.mvi.UIComponentViewModelProvider
import org.mozilla.fenix.mvi.ViewState
import org.mozilla.fenix.test.Mockable
data class ExceptionsItem(val url: String)
@ -38,6 +38,7 @@ class ExceptionsComponent(
data class ExceptionsState(val items: List<ExceptionsItem>) : ViewState
sealed class ExceptionsAction : Action {
object LearnMore : ExceptionsAction()
sealed class Delete : ExceptionsAction() {
object All : Delete()
data class One(val item: ExceptionsItem) : Delete()

View File

@ -17,11 +17,14 @@ import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.FenixViewModelProvider
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.mvi.ActionBusFactory
import org.mozilla.fenix.mvi.getAutoDisposeObservable
import org.mozilla.fenix.mvi.getManagedEmitter
import org.mozilla.fenix.settings.SupportUtils
class ExceptionsFragment : Fragment() {
private lateinit var exceptionsComponent: ExceptionsComponent
@ -56,6 +59,14 @@ class ExceptionsFragment : Fragment() {
getAutoDisposeObservable<ExceptionsAction>()
.subscribe {
when (it) {
is ExceptionsAction.LearnMore -> {
(activity as HomeActivity).openToBrowserAndLoad(
searchTermOrURL = SupportUtils.getGenericSumoURLForTopic
(SupportUtils.SumoTopic.TRACKING_PROTECTION),
newTab = true,
from = BrowserDirection.FromExceptions
)
}
is ExceptionsAction.Delete.All -> viewLifecycleOwner.lifecycleScope.launch(IO) {
val domains = ExceptionDomains.load(context!!)
ExceptionDomains.remove(context!!, domains)

View File

@ -4,10 +4,15 @@
package org.mozilla.fenix.exceptions
import android.text.SpannableString
import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.text.style.ForegroundColorSpan
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.functions.Consumer
@ -20,20 +25,45 @@ class ExceptionsUIView(
actionEmitter: Observer<ExceptionsAction>,
changesObservable: Observable<ExceptionsChange>
) :
UIView<ExceptionsState, ExceptionsAction, ExceptionsChange>(container, actionEmitter, changesObservable) {
UIView<ExceptionsState, ExceptionsAction, ExceptionsChange>(
container,
actionEmitter,
changesObservable
) {
override val view: RecyclerView = LayoutInflater.from(container.context)
override val view: FrameLayout = LayoutInflater.from(container.context)
.inflate(R.layout.component_exceptions, container, true)
.findViewById(R.id.exceptions_list)
.findViewById(R.id.exceptions_wrapper)
init {
view.exceptions_list.apply {
adapter = ExceptionsAdapter(actionEmitter)
layoutManager = LinearLayoutManager(container.context)
}
val descriptionText = String
.format(
view.exceptions_empty_view.text.toString(),
System.getProperty("line.separator")
)
val linkStartIndex = descriptionText.indexOf("\n\n") + 2
val linkAction = object : ClickableSpan() {
override fun onClick(widget: View?) {
actionEmitter.onNext(ExceptionsAction.LearnMore)
}
}
val textWithLink = SpannableString(descriptionText).apply {
setSpan(linkAction, linkStartIndex, descriptionText.length, 0)
val colorSpan = ForegroundColorSpan(view.exceptions_empty_view.currentTextColor)
setSpan(colorSpan, linkStartIndex, descriptionText.length, 0)
}
view.exceptions_empty_view.movementMethod = LinkMovementMethod.getInstance()
view.exceptions_empty_view.text = textWithLink
}
override fun updateView() = Consumer<ExceptionsState> {
view.exceptions_empty_view.visibility = if (it.items.isEmpty()) View.VISIBLE else View.GONE
view.exceptions_list.visibility = if (it.items.isEmpty()) View.GONE else View.VISIBLE
(view.exceptions_list.adapter as ExceptionsAdapter).updateData(it.items)
}
}

View File

@ -28,7 +28,8 @@ object SupportUtils {
) {
HELP("faq-android"),
PRIVATE_BROWSING_MYTHS("common-myths-about-private-browsing"),
YOUR_RIGHTS("your-rights")
YOUR_RIGHTS("your-rights"),
TRACKING_PROTECTION("tracking-protection-firefox-preview")
}
fun getSumoURLForTopic(context: Context, topic: SumoTopic): String {

View File

@ -11,7 +11,6 @@ import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SwitchPreference
import org.mozilla.fenix.R
import org.mozilla.fenix.exceptions.ExceptionDomains
import org.mozilla.fenix.ext.getPreferenceKey
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.utils.Settings
@ -34,7 +33,8 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() {
preferenceTP?.isChecked = Settings.getInstance(context!!).shouldUseTrackingProtection
preferenceTP?.onPreferenceChangeListener =
Preference.OnPreferenceChangeListener { _, newValue ->
Settings.getInstance(requireContext()).setTrackingProtection(newValue = newValue as Boolean)
Settings.getInstance(requireContext())
.setTrackingProtection(newValue = newValue as Boolean)
with(requireComponents) {
val policy = core.createTrackingProtectionPolicy(newValue)
useCases.settingsUseCases.updateTrackingProtection.invoke(policy)
@ -43,20 +43,16 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() {
true
}
context?.let {
val exceptionsEmpty = ExceptionDomains.load(it).isEmpty()
val exceptions =
it.getPreferenceKey(R.string.pref_key_tracking_protection_exceptions)
val preferenceExceptions = findPreference<Preference>(exceptions)
preferenceExceptions?.shouldDisableView = true
preferenceExceptions?.isEnabled = !exceptionsEmpty
preferenceExceptions?.onPreferenceClickListener = getClickListenerForExceptions()
}
val exceptions =
context!!.getPreferenceKey(R.string.pref_key_tracking_protection_exceptions)
val preferenceExceptions = findPreference<Preference>(exceptions)
preferenceExceptions?.onPreferenceClickListener = getClickListenerForExceptions()
}
private fun getClickListenerForExceptions(): Preference.OnPreferenceClickListener {
return Preference.OnPreferenceClickListener {
val directions = TrackingProtectionFragmentDirections.actionTrackingProtectionFragmentToExceptionsFragment()
val directions =
TrackingProtectionFragmentDirections.actionTrackingProtectionFragmentToExceptionsFragment()
Navigation.findNavController(view!!).navigate(directions)
true
}

View File

@ -2,10 +2,27 @@
<!-- 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/. -->
<androidx.recyclerview.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/exceptions_wrapper"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:visibility="gone"
android:id="@+id/exceptions_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="@layout/exception_item"/>
tools:listitem="@layout/exception_item" />
<TextView
android:id="@+id/exceptions_empty_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_margin="12dp"
android:text="@string/exceptions_empty_message"
android:textColor="?secondaryText"
android:textSize="16sp"
android:visibility="visible" />
</FrameLayout>

View File

@ -375,11 +375,17 @@
<fragment
android:id="@+id/deleteBrowsingDataFragment"
android:name="org.mozilla.fenix.settings.DeleteBrowsingDataFragment"
android:label="@string/preferences_delete_browsing_data"/>
android:label="@string/preferences_delete_browsing_data" />
<fragment
android:id="@+id/exceptionsFragment"
android:name="org.mozilla.fenix.exceptions.ExceptionsFragment"
android:label="@string/preference_exceptions" />
android:label="@string/preference_exceptions">
<action
android:id="@+id/action_exceptionsFragment_to_browserFragment"
app:destination="@id/browserFragment"
app:popUpTo="@id/settingsFragment"
app:popUpToInclusive="true" />
</fragment>
<dialog
android:id="@+id/createCollectionFragment"
android:name="org.mozilla.fenix.collections.CreateCollectionFragment"

View File

@ -197,6 +197,8 @@
<string name="preferences_tracking_protection_exceptions_description">Tracking Protection is off for these websites</string>
<!-- Button in Exceptions Preference to turn on tracking protection for all sites (remove all exceptions) -->
<string name="preferences_tracking_protection_exceptions_turn_on_for_all">Turn on for all sites</string>
<!-- Text displayed when there are no exceptions, includes a learn more link that brings users to a tracking protection SUMO page -->
<string name="exceptions_empty_message">Exceptions let you disable tracking protection for selected sites.\n\nLearn more</string>
<!-- Description in Quick Settings that tells user tracking protection is off globally for all sites, and links to Settings to turn it on -->
<string name="preferences_tracking_protection_turned_off_globally">Turned off globally, go to Settings to turn it on.</string>