diff --git a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt index a2aca84a0..826df865d 100644 --- a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt @@ -12,6 +12,7 @@ import android.view.View import androidx.annotation.IdRes import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar +import androidx.lifecycle.lifecycleScope import androidx.navigation.NavController import androidx.navigation.fragment.NavHostFragment import androidx.navigation.ui.AppBarConfiguration @@ -19,8 +20,6 @@ import androidx.navigation.ui.NavigationUI import io.sentry.Sentry import io.sentry.event.Breadcrumb import io.sentry.event.BreadcrumbBuilder -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import mozilla.components.browser.search.SearchEngine import mozilla.components.browser.session.Session @@ -138,13 +137,15 @@ open class HomeActivity : AppCompatActivity() { override fun onResume() { super.onResume() - CoroutineScope(Dispatchers.Main).launch { - // Make sure accountManager is initialized. - components.backgroundServices.accountManager.initAsync().await() - // If we're authenticated, kick-off a sync and a device state refresh. - components.backgroundServices.accountManager.authenticatedAccount()?.let { - components.backgroundServices.syncManager?.syncNow(startup = true) - it.deviceConstellation().refreshDeviceStateAsync().await() + lifecycleScope.launch { + with(components.backgroundServices) { + // Make sure accountManager is initialized. + accountManager.initAsync().await() + // If we're authenticated, kick-off a sync and a device state refresh. + accountManager.authenticatedAccount()?.let { + syncManager?.syncNow(startup = true) + it.deviceConstellation().refreshDeviceStateAsync().await() + } } } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/AccountProblemFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/AccountProblemFragment.kt index b8014ad8b..fda384cab 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/AccountProblemFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/AccountProblemFragment.kt @@ -6,12 +6,11 @@ package org.mozilla.fenix.settings import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.navigation.Navigation import androidx.navigation.fragment.NavHostFragment import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import mozilla.components.concept.sync.AccountObserver import mozilla.components.concept.sync.OAuthAccount @@ -68,7 +67,7 @@ class AccountProblemFragment : PreferenceFragmentCompat(), AccountObserver { private fun getClickListenerForSignOut(): Preference.OnPreferenceClickListener { return Preference.OnPreferenceClickListener { - CoroutineScope(Dispatchers.Main).launch { + lifecycleScope.launch { requireComponents.backgroundServices.accountManager.logoutAsync().await() Navigation.findNavController(view!!).popBackStack() } @@ -78,7 +77,7 @@ class AccountProblemFragment : PreferenceFragmentCompat(), AccountObserver { // We're told our auth problems have been fixed; close this fragment. override fun onAuthenticated(account: OAuthAccount) { - CoroutineScope(Dispatchers.Main).launch { + lifecycleScope.launch { NavHostFragment.findNavController(this@AccountProblemFragment).popBackStack() } } @@ -89,7 +88,7 @@ class AccountProblemFragment : PreferenceFragmentCompat(), AccountObserver { // We're told there are no more auth problems since there is no more account; close this fragment. override fun onLoggedOut() { - CoroutineScope(Dispatchers.Main).launch { + lifecycleScope.launch { NavHostFragment.findNavController(this@AccountProblemFragment).popBackStack() } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/AccountSettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/AccountSettingsFragment.kt index d6fe662a0..cdc0d25d5 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/AccountSettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/AccountSettingsFragment.kt @@ -9,22 +9,21 @@ import android.os.Bundle import android.text.InputFilter import android.text.format.DateUtils import androidx.appcompat.app.AppCompatActivity -import androidx.navigation.Navigation +import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController import androidx.preference.CheckBoxPreference import androidx.preference.EditTextPreference import androidx.preference.Preference import androidx.preference.PreferenceCategory import androidx.preference.PreferenceFragmentCompat import androidx.preference.forEach -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job +import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.launch import mozilla.components.concept.sync.AccountObserver import mozilla.components.concept.sync.ConstellationState +import mozilla.components.concept.sync.DeviceConstellationObserver import mozilla.components.concept.sync.OAuthAccount import mozilla.components.concept.sync.Profile -import mozilla.components.concept.sync.DeviceConstellationObserver import mozilla.components.concept.sync.SyncStatusObserver import mozilla.components.feature.sync.getLastSynced import mozilla.components.service.fxa.FxaException @@ -35,13 +34,8 @@ import org.mozilla.fenix.R import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.ext.getPreferenceKey import org.mozilla.fenix.ext.requireComponents -import kotlin.Exception -import kotlin.coroutines.CoroutineContext -class AccountSettingsFragment : PreferenceFragmentCompat(), CoroutineScope { - private lateinit var job: Job - override val coroutineContext: CoroutineContext - get() = Dispatchers.Main + job +class AccountSettingsFragment : PreferenceFragmentCompat() { private lateinit var accountManager: FxaAccountManager // Navigate away from this fragment when we encounter auth problems or logout events. @@ -49,16 +43,16 @@ class AccountSettingsFragment : PreferenceFragmentCompat(), CoroutineScope { override fun onAuthenticated(account: OAuthAccount) {} override fun onAuthenticationProblems() { - launch { - Navigation.findNavController(view!!).popBackStack() + lifecycleScope.launch { + findNavController().popBackStack() } } override fun onError(error: Exception) {} override fun onLoggedOut() { - launch { - Navigation.findNavController(view!!).popBackStack() + lifecycleScope.launch { + findNavController().popBackStack() // Remove the device name when we log out. context?.let { @@ -79,13 +73,11 @@ class AccountSettingsFragment : PreferenceFragmentCompat(), CoroutineScope { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - job = Job() requireComponents.analytics.metrics.track(Event.SyncAccountOpened) } override fun onDestroy() { super.onDestroy() - job.cancel() requireComponents.analytics.metrics.track(Event.SyncAccountClosed) } @@ -141,7 +133,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat(), CoroutineScope { private fun getClickListenerForSignOut(): Preference.OnPreferenceClickListener { return Preference.OnPreferenceClickListener { requireComponents.analytics.metrics.track(Event.SyncAccountSignOut) - launch { + lifecycleScope.launch { accountManager.logoutAsync().await() } true @@ -154,7 +146,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat(), CoroutineScope { requireComponents.analytics.metrics.track(Event.SyncAccountSyncNow) requireComponents.backgroundServices.syncManager?.syncNow() // Poll for device events. - launch { + lifecycleScope.launch { accountManager.authenticatedAccount() ?.deviceConstellation() ?.refreshDeviceStateAsync() @@ -172,7 +164,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat(), CoroutineScope { preferenceDeviceName?.summary = newValue as String // This may fail, and we'll have a disparity in the UI until `updateDeviceName` is called. - CoroutineScope(Dispatchers.IO).launch { + lifecycleScope.launch(IO) { try { accountManager.authenticatedAccount()?.let { it.deviceConstellation().setDeviceNameAsync(newValue) @@ -189,9 +181,11 @@ class AccountSettingsFragment : PreferenceFragmentCompat(), CoroutineScope { } private val syncStatusObserver = object : SyncStatusObserver { + private val key = context!!.getPreferenceKey(R.string.pref_key_sync_now) + override fun onStarted() { - CoroutineScope(Dispatchers.Main).launch { - val pref = findPreference(context!!.getPreferenceKey(R.string.pref_key_sync_now)) + lifecycleScope.launch { + val pref = findPreference(key) view?.announceForAccessibility(getString(R.string.sync_syncing_in_progress)) pref?.title = getString(R.string.sync_syncing_in_progress) pref?.isEnabled = false @@ -202,9 +196,8 @@ class AccountSettingsFragment : PreferenceFragmentCompat(), CoroutineScope { // Sync stopped successfully. override fun onIdle() { - CoroutineScope(Dispatchers.Main).launch { - val pref = findPreference(context!!.getPreferenceKey(R.string.pref_key_sync_now)) - pref?.let { + lifecycleScope.launch { + findPreference(key)?.let { pref -> pref.title = getString(R.string.preferences_sync_now) pref.isEnabled = true updateLastSyncedTimePref(context!!, pref, failed = false) @@ -214,9 +207,8 @@ class AccountSettingsFragment : PreferenceFragmentCompat(), CoroutineScope { // Sync stopped after encountering a problem. override fun onError(error: Exception?) { - CoroutineScope(Dispatchers.Main).launch { - val pref = findPreference(context!!.getPreferenceKey(R.string.pref_key_sync_now)) - pref?.let { + lifecycleScope.launch { + findPreference(key)?.let { pref -> pref.title = getString(R.string.preferences_sync_now) pref.isEnabled = true updateLastSyncedTimePref(context!!, pref, failed = true) diff --git a/app/src/main/java/org/mozilla/fenix/settings/DeleteBrowsingDataFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/DeleteBrowsingDataFragment.kt index b181ed075..e75e529ce 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/DeleteBrowsingDataFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/DeleteBrowsingDataFragment.kt @@ -13,11 +13,10 @@ import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import androidx.lifecycle.Observer +import androidx.lifecycle.lifecycleScope import kotlinx.android.synthetic.main.fragment_delete_browsing_data.* import kotlinx.android.synthetic.main.fragment_delete_browsing_data.view.* -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -28,23 +27,17 @@ import mozilla.components.feature.tab.collections.TabCollection import org.mozilla.fenix.R import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.ext.requireComponents -import kotlin.coroutines.CoroutineContext @SuppressWarnings("TooManyFunctions") -class DeleteBrowsingDataFragment : Fragment(), CoroutineScope { +class DeleteBrowsingDataFragment : Fragment() { private lateinit var sessionObserver: SessionManager.Observer private var tabCollections: List = listOf() - private lateinit var job: Job - override val coroutineContext: CoroutineContext - get() = Dispatchers.Main + job - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = inflater.inflate(R.layout.fragment_delete_browsing_data, container, false) override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - job = Job() sessionObserver = object : SessionManager.Observer { override fun onSessionAdded(session: Session) { @@ -88,11 +81,6 @@ class DeleteBrowsingDataFragment : Fragment(), CoroutineScope { } } - override fun onDestroyView() { - super.onDestroyView() - job.cancel() - } - override fun onResume() { super.onResume() (activity as AppCompatActivity).apply { @@ -132,7 +120,7 @@ class DeleteBrowsingDataFragment : Fragment(), CoroutineScope { val collectionsChecked = view!!.collections_item!!.isChecked startDeletion() - launch(Dispatchers.IO) { + viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) { if (openTabsChecked) deleteTabs() if (browsingDataChecked) deleteBrowsingData() if (collectionsChecked) deleteCollections() @@ -187,7 +175,7 @@ class DeleteBrowsingDataFragment : Fragment(), CoroutineScope { private fun updateHistoryCount() { view?.browsing_data_item?.subtitleView?.text = "" - launch(Dispatchers.IO) { + viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) { val historyCount = requireComponents.core.historyStorage.getVisited().size launch(Dispatchers.Main) { view?.browsing_data_item?.apply { @@ -204,7 +192,7 @@ class DeleteBrowsingDataFragment : Fragment(), CoroutineScope { private fun updateCollectionsCount() { view?.browsing_data_item?.subtitleView?.text = "" - launch(Dispatchers.IO) { + viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) { val collectionsCount = requireComponents.core.tabCollectionStorage.getTabCollectionsCount() launch(Dispatchers.Main) { view?.collections_item?.apply { diff --git a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt index d3d646eab..f23bb75d4 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt @@ -13,13 +13,12 @@ import android.os.Bundle import android.provider.Settings import android.widget.Toast import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.navigation.Navigation import androidx.preference.Preference import androidx.preference.Preference.OnPreferenceClickListener import androidx.preference.PreferenceCategory import androidx.preference.PreferenceFragmentCompat -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import mozilla.components.concept.sync.AccountObserver import mozilla.components.concept.sync.OAuthAccount @@ -326,7 +325,7 @@ class SettingsFragment : PreferenceFragmentCompat(), AccountObserver { } override fun onAuthenticated(account: OAuthAccount) { - CoroutineScope(Dispatchers.Main).launch { + lifecycleScope.launch { context?.let { updateAccountUIState(it, it.components.backgroundServices.accountManager.accountProfile()) } @@ -336,7 +335,7 @@ class SettingsFragment : PreferenceFragmentCompat(), AccountObserver { override fun onError(error: Exception) {} override fun onLoggedOut() { - CoroutineScope(Dispatchers.Main).launch { + lifecycleScope.launch { context?.let { updateAccountUIState(it, it.components.backgroundServices.accountManager.accountProfile()) } @@ -344,7 +343,7 @@ class SettingsFragment : PreferenceFragmentCompat(), AccountObserver { } override fun onProfileUpdated(profile: Profile) { - CoroutineScope(Dispatchers.Main).launch { + lifecycleScope.launch { context?.let { updateAccountUIState(it, profile) } @@ -352,7 +351,7 @@ class SettingsFragment : PreferenceFragmentCompat(), AccountObserver { } override fun onAuthenticationProblems() { - CoroutineScope(Dispatchers.Main).launch { + lifecycleScope.launch { context?.let { updateAccountUIState(it, it.components.backgroundServices.accountManager.accountProfile()) } diff --git a/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsDetailsExceptionsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsDetailsExceptionsFragment.kt index 96bb8ba7c..a1e7da49f 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsDetailsExceptionsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsDetailsExceptionsFragment.kt @@ -6,14 +6,12 @@ package org.mozilla.fenix.settings import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.navigation.Navigation import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.Main -import kotlinx.coroutines.Job import kotlinx.coroutines.launch import mozilla.components.feature.sitepermissions.SitePermissions import org.jetbrains.anko.alert @@ -22,15 +20,12 @@ import org.jetbrains.anko.yesButton import org.mozilla.fenix.R import org.mozilla.fenix.ext.components import org.mozilla.fenix.settings.PhoneFeature.CAMERA -import org.mozilla.fenix.settings.PhoneFeature.MICROPHONE import org.mozilla.fenix.settings.PhoneFeature.LOCATION +import org.mozilla.fenix.settings.PhoneFeature.MICROPHONE import org.mozilla.fenix.settings.PhoneFeature.NOTIFICATION -import kotlin.coroutines.CoroutineContext @SuppressWarnings("TooManyFunctions") -class SitePermissionsDetailsExceptionsFragment : PreferenceFragmentCompat(), CoroutineScope { - private lateinit var job: Job - override val coroutineContext: CoroutineContext get() = Dispatchers.IO + job +class SitePermissionsDetailsExceptionsFragment : PreferenceFragmentCompat() { private lateinit var sitePermissions: SitePermissions override fun onCreate(savedInstanceState: Bundle?) { @@ -42,7 +37,6 @@ class SitePermissionsDetailsExceptionsFragment : PreferenceFragmentCompat(), Cor .sitePermissions (activity as AppCompatActivity).title = sitePermissions.origin - job = Job() } override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { @@ -51,7 +45,7 @@ class SitePermissionsDetailsExceptionsFragment : PreferenceFragmentCompat(), Cor override fun onResume() { super.onResume() - launch(IO) { + lifecycleScope.launch(IO) { val context = requireContext() sitePermissions = requireNotNull(context.components.core.permissionStorage.findSitePermissionsBy(sitePermissions.origin)) @@ -61,11 +55,6 @@ class SitePermissionsDetailsExceptionsFragment : PreferenceFragmentCompat(), Cor } } - override fun onDestroy() { - super.onDestroy() - job.cancel() - } - private fun bindCategoryPhoneFeatures() { val context = requireContext() @@ -112,7 +101,7 @@ class SitePermissionsDetailsExceptionsFragment : PreferenceFragmentCompat(), Cor } private fun clearSitePermissions() { - launch(IO) { + lifecycleScope.launch(IO) { requireContext().components.core.permissionStorage.deleteSitePermissions(sitePermissions) launch(Main) { Navigation.findNavController(requireNotNull(view)).popBackStack() diff --git a/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsExceptionsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsExceptionsFragment.kt index dfb340155..2a64d6f6c 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsExceptionsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsExceptionsFragment.kt @@ -4,6 +4,7 @@ package org.mozilla.fenix.settings +import android.graphics.drawable.BitmapDrawable import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -11,10 +12,12 @@ import android.view.View.GONE import android.view.View.VISIBLE import android.view.ViewGroup import android.widget.Button +import android.widget.ImageView import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import androidx.lifecycle.Observer +import androidx.lifecycle.lifecycleScope import androidx.paging.LivePagedListBuilder import androidx.paging.PagedList import androidx.paging.PagedListAdapter @@ -22,7 +25,6 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Job @@ -34,25 +36,20 @@ import org.jetbrains.anko.noButton import org.jetbrains.anko.yesButton import org.mozilla.fenix.R import org.mozilla.fenix.ext.components -import kotlin.coroutines.CoroutineContext -import android.graphics.drawable.BitmapDrawable -import android.widget.ImageView import org.mozilla.fenix.ext.nav +import kotlin.coroutines.CoroutineContext private const val MAX_ITEMS_PER_PAGE = 50 @SuppressWarnings("TooManyFunctions") -class SitePermissionsExceptionsFragment : Fragment(), View.OnClickListener, CoroutineScope { +class SitePermissionsExceptionsFragment : Fragment(), View.OnClickListener { private lateinit var emptyContainerMessage: View private lateinit var recyclerView: RecyclerView private lateinit var clearButton: Button - private lateinit var job: Job - override val coroutineContext: CoroutineContext get() = Dispatchers.IO + job override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) (activity as AppCompatActivity).supportActionBar?.show() - job = Job() } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { @@ -117,13 +114,8 @@ class SitePermissionsExceptionsFragment : Fragment(), View.OnClickListener, Coro } } - override fun onDestroy() { - super.onDestroy() - job.cancel() - } - private fun deleteAllSitePermissions() { - launch(IO) { + lifecycleScope.launch(IO) { requireContext().components.core.permissionStorage.deleteAllSitePermissions() launch(Main) { showEmptyListMessage() diff --git a/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsManageExceptionsPhoneFeatureFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsManageExceptionsPhoneFeatureFragment.kt index d90f305d3..36906355a 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsManageExceptionsPhoneFeatureFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SitePermissionsManageExceptionsPhoneFeatureFragment.kt @@ -15,10 +15,8 @@ import android.widget.Button import android.widget.RadioButton import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers +import androidx.lifecycle.lifecycleScope import kotlinx.coroutines.Dispatchers.IO -import kotlinx.coroutines.Job import kotlinx.coroutines.launch import mozilla.components.feature.sitepermissions.SitePermissions import mozilla.components.feature.sitepermissions.SitePermissions.Status.ALLOWED @@ -27,21 +25,18 @@ import org.jetbrains.anko.alert import org.jetbrains.anko.noButton import org.jetbrains.anko.yesButton import org.mozilla.fenix.R -import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.utils.Settings -import kotlin.coroutines.CoroutineContext @SuppressWarnings("TooManyFunctions") -class SitePermissionsManageExceptionsPhoneFeatureFragment : Fragment(), CoroutineScope { +class SitePermissionsManageExceptionsPhoneFeatureFragment : Fragment() { private lateinit var phoneFeature: PhoneFeature private lateinit var sitePermissions: SitePermissions private lateinit var radioAllow: RadioButton private lateinit var radioBlock: RadioButton private lateinit var blockedByAndroidView: View - private lateinit var job: Job val settings by lazy { Settings.getInstance(requireContext()) } - override val coroutineContext: CoroutineContext get() = Dispatchers.IO + job override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -55,7 +50,6 @@ class SitePermissionsManageExceptionsPhoneFeatureFragment : Fragment(), Coroutin (activity as AppCompatActivity).title = phoneFeature.getLabel(requireContext()) (activity as AppCompatActivity).supportActionBar?.show() - job = Job() } override fun onCreateView( @@ -79,11 +73,6 @@ class SitePermissionsManageExceptionsPhoneFeatureFragment : Fragment(), Coroutin initBlockedByAndroidView(phoneFeature, blockedByAndroidView) } - override fun onDestroy() { - super.onDestroy() - job.cancel() - } - private fun initAskToAllowRadio(rootView: View) { radioAllow = rootView.findViewById(R.id.ask_to_allow_radio) val askToAllowText = getString(R.string.preference_option_phone_feature_allowed) @@ -171,8 +160,8 @@ class SitePermissionsManageExceptionsPhoneFeatureFragment : Fragment(), Coroutin PhoneFeature.MICROPHONE -> sitePermissions.copy(microphone = status) PhoneFeature.NOTIFICATION -> sitePermissions.copy(notification = status) } - launch(IO) { - requireContext().components.core.permissionStorage.updateSitePermissions(updatedSitePermissions) + lifecycleScope.launch(IO) { + requireComponents.core.permissionStorage.updateSitePermissions(updatedSitePermissions) } } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsSheetDialogFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsSheetDialogFragment.kt index 8478dcc9b..d83963e5e 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsSheetDialogFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsSheetDialogFragment.kt @@ -20,11 +20,10 @@ import androidx.appcompat.app.AppCompatDialogFragment import androidx.appcompat.view.ContextThemeWrapper import androidx.core.net.toUri import androidx.core.widget.NestedScrollView +import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.NavHostFragment.findNavController import com.google.android.material.bottomsheet.BottomSheetDialog -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job import kotlinx.coroutines.launch import mozilla.components.browser.session.Session import mozilla.components.feature.sitepermissions.SitePermissions @@ -43,12 +42,11 @@ import org.mozilla.fenix.mvi.getManagedEmitter import org.mozilla.fenix.settings.PhoneFeature import java.net.MalformedURLException import java.net.URL -import kotlin.coroutines.CoroutineContext private const val REQUEST_CODE_QUICK_SETTINGS_PERMISSIONS = 4 @SuppressWarnings("TooManyFunctions") -class QuickSettingsSheetDialogFragment : AppCompatDialogFragment(), CoroutineScope { +class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() { private val safeArguments get() = requireNotNull(arguments) private val sessionId: String by lazy { QuickSettingsSheetDialogFragmentArgs.fromBundle(safeArguments).sessionId } private val url: String by lazy { QuickSettingsSheetDialogFragmentArgs.fromBundle(safeArguments).url } @@ -58,17 +56,9 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment(), CoroutineSco } private val promptGravity: Int by lazy { QuickSettingsSheetDialogFragmentArgs.fromBundle(safeArguments).gravity } private lateinit var quickSettingsComponent: QuickSettingsComponent - private lateinit var job: Job private var sitePermissions: SitePermissions? = null - override val coroutineContext: CoroutineContext get() = Dispatchers.IO + job - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - job = Job() - } - override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -150,11 +140,6 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment(), CoroutineSco } } - override fun onDestroy() { - super.onDestroy() - job.cancel() - } - private fun arePermissionsGranted(requestCode: Int, grantResults: IntArray) = requestCode == REQUEST_CODE_QUICK_SETTINGS_PERMISSIONS && grantResults.all { it == PERMISSION_GRANTED } @@ -164,7 +149,7 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment(), CoroutineSco } catch (e: MalformedURLException) { url } - launch { + lifecycleScope.launch { if (!ExceptionDomains.load(context).contains(host)) { ExceptionDomains.add(context, host) } else { @@ -188,7 +173,7 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment(), CoroutineSco findNavController(this@QuickSettingsSheetDialogFragment).navigate(directions) } is QuickSettingsAction.SelectReportProblem -> { - launch(Dispatchers.Main) { + lifecycleScope.launch(Dispatchers.Main) { val reportUrl = String.format(BrowserFragment.REPORT_SITE_ISSUE_URL, it.url) requireComponents.useCases.tabsUseCases.addTab.invoke(reportUrl) @@ -204,7 +189,7 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment(), CoroutineSco is QuickSettingsAction.ToggleTrackingProtection -> { val trackingEnabled = it.trackingProtection context?.let { context: Context -> toggleTrackingProtection(context, url) } - launch(Dispatchers.Main) { + lifecycleScope.launch(Dispatchers.Main) { getManagedEmitter().onNext( QuickSettingsChange.Change( url, @@ -218,7 +203,7 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment(), CoroutineSco } is QuickSettingsAction.TogglePermission -> { - launch { + lifecycleScope.launch { sitePermissions = quickSettingsComponent.toggleSitePermission( context = requireContext(), featurePhone = it.featurePhone, @@ -251,7 +236,7 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment(), CoroutineSco private val sessionObserver = object : Session.Observer { override fun onUrlChanged(session: Session, url: String) { super.onUrlChanged(session, url) - launch { + lifecycleScope.launch { val host = session.url.toUri()?.host val sitePermissions: SitePermissions? = host?.let { val storage = requireContext().components.core.permissionStorage diff --git a/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt b/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt index b2b5ce8f0..65c1dae5e 100644 --- a/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt @@ -18,9 +18,6 @@ import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatDialogFragment import kotlinx.android.parcel.Parcelize import kotlinx.android.synthetic.main.fragment_share.view.* -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job import mozilla.components.concept.sync.DeviceEventOutgoing import mozilla.components.concept.sync.OAuthAccount import org.mozilla.fenix.FenixViewModelProvider @@ -29,12 +26,8 @@ import org.mozilla.fenix.ext.nav import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.mvi.ActionBusFactory import org.mozilla.fenix.mvi.getAutoDisposeObservable -import kotlin.coroutines.CoroutineContext -class ShareFragment : AppCompatDialogFragment(), CoroutineScope { - override val coroutineContext: CoroutineContext - get() = Dispatchers.Main + job - private lateinit var job: Job +class ShareFragment : AppCompatDialogFragment() { private lateinit var component: ShareComponent private var tabs: Array = emptyArray() @@ -51,7 +44,6 @@ class ShareFragment : AppCompatDialogFragment(), CoroutineScope { throw IllegalStateException("URL and tabs cannot both be null.") } - job = Job() tabs = args.tabs ?: arrayOf(ShareTab(args.url!!, args.title ?: "")) component = ShareComponent( @@ -73,11 +65,6 @@ class ShareFragment : AppCompatDialogFragment(), CoroutineScope { subscribeToActions() } - override fun onDestroyView() { - super.onDestroyView() - job.cancel() - } - @SuppressWarnings("ComplexMethod") private fun subscribeToActions() { getAutoDisposeObservable().subscribe { diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index 2910858a5..a402c1736 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -152,7 +152,7 @@ object Deps { const val androidx_lifecycle_viewmodel_ss = "androidx.lifecycle:lifecycle-viewmodel-savedstate:${Versions.androidx_lifecycle_savedstate}" const val androidx_preference = "androidx.preference:preference-ktx:${Versions.androidx_preference}" const val androidx_safeargs = "androidx.navigation:navigation-safe-args-gradle-plugin:${Versions.androidx_navigation}" - const val androidx_navigation_fragment = "androidx.navigation:navigation-fragment:${Versions.androidx_navigation}" + const val androidx_navigation_fragment = "androidx.navigation:navigation-fragment-ktx:${Versions.androidx_navigation}" const val androidx_navigation_ui = "androidx.navigation:navigation-ui:${Versions.androidx_navigation}" const val androidx_recyclerview = "androidx.recyclerview:recyclerview:${Versions.androidx_recyclerview}" const val androidx_core = "androidx.core:core:${Versions.androidx_core}"