diff --git a/CHANGELOG.md b/CHANGELOG.md index bf4ae9b0a..f206b247e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - #4137 - Adds pagination to the history view - #3695 - Made search suggestions for other tabs clickable + +### Changed - Remove forced focus of toolbar on homescreen +- #4529 - Fixed an issue where the app would sometimes return to a blank toolbar +- #4427 - Fixed an issue where the app would sometimes return to the home fragment + +### Removed ## [1.1.0 and earlier] - 2019-07-23 ### Added diff --git a/app/src/main/java/org/mozilla/fenix/FenixViewModelProvider.kt b/app/src/main/java/org/mozilla/fenix/FenixViewModelProvider.kt index bfc3867e5..c9d049795 100644 --- a/app/src/main/java/org/mozilla/fenix/FenixViewModelProvider.kt +++ b/app/src/main/java/org/mozilla/fenix/FenixViewModelProvider.kt @@ -7,10 +7,10 @@ package org.mozilla.fenix import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider -import org.mozilla.fenix.mvi.ViewState import org.mozilla.fenix.mvi.Change import org.mozilla.fenix.mvi.UIComponentViewModelBase import org.mozilla.fenix.mvi.UIComponentViewModelProvider +import org.mozilla.fenix.mvi.ViewState object FenixViewModelProvider { fun > create( diff --git a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt index 74a7122c1..c205833f6 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt @@ -15,7 +15,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.net.toUri import androidx.fragment.app.Fragment -import androidx.lifecycle.ViewModelProvider +import androidx.fragment.app.activityViewModels import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController import com.google.android.material.bottomsheet.BottomSheetBehavior @@ -25,9 +25,12 @@ import kotlinx.android.synthetic.main.fragment_browser.* import kotlinx.android.synthetic.main.fragment_browser.view.* import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.Main +import kotlinx.coroutines.Job +import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import mozilla.components.browser.session.Session +import mozilla.components.browser.session.SessionManager import mozilla.components.browser.session.intent.EXTRA_SESSION_ID import mozilla.components.feature.app.links.AppLinksFeature import mozilla.components.feature.contextmenu.ContextMenuFeature @@ -76,8 +79,8 @@ import org.mozilla.fenix.utils.Settings * This class only contains shared code focused on the main browsing content. * UI code specific to the app or to custom tabs can be found in the subclasses. */ -@Suppress("TooManyFunctions") -abstract class BaseBrowserFragment : Fragment(), BackHandler { +@Suppress("TooManyFunctions", "LargeClass") +abstract class BaseBrowserFragment : Fragment(), BackHandler, SessionManager.Observer { protected lateinit var browserStore: BrowserStore protected lateinit var browserInteractor: BrowserInteractor protected lateinit var browserToolbarView: BrowserToolbarView @@ -95,6 +98,9 @@ abstract class BaseBrowserFragment : Fragment(), BackHandler { var customTabSessionId: String? = null + private var browserInitialized: Boolean = false + private var initUIJob: Job? = null + @CallSuper override fun onCreateView( inflater: LayoutInflater, @@ -127,17 +133,19 @@ abstract class BaseBrowserFragment : Fragment(), BackHandler { return view } - @Suppress("ComplexMethod") @CallSuper override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + browserInitialized = initializeUI(view) != null + } + @Suppress("ComplexMethod") + @CallSuper + protected open fun initializeUI(view: View): Session? { val sessionManager = requireComponents.core.sessionManager - getSessionById()?.let { session -> - val viewModel = activity!!.run { - ViewModelProvider(this).get(CreateCollectionViewModel::class.java) - } + return getSessionById()?.also { session -> + val viewModel: CreateCollectionViewModel by activityViewModels() val browserToolbarController = DefaultBrowserToolbarController( context!!, @@ -185,157 +193,179 @@ abstract class BaseBrowserFragment : Fragment(), BackHandler { browserToolbarView.view.setOnSiteSecurityClickedListener { showQuickSettingsDialog() } - } - contextMenuFeature.set( - feature = ContextMenuFeature( - requireFragmentManager(), - sessionManager, - FenixContextMenuCandidate.defaultCandidates( - requireContext(), - requireComponents.useCases.tabsUseCases, - view, - FenixSnackbarDelegate( + contextMenuFeature.set( + feature = ContextMenuFeature( + requireFragmentManager(), + sessionManager, + FenixContextMenuCandidate.defaultCandidates( + requireContext(), + requireComponents.useCases.tabsUseCases, view, - if (getSessionById()?.isCustomTabSession() == true) null else nestedScrollQuickAction - ) - ), - view.engineView - ), - owner = this, - view = view - ) - - downloadsFeature.set( - feature = DownloadsFeature( - requireContext().applicationContext, - sessionManager = sessionManager, - fragmentManager = childFragmentManager, - sessionId = customTabSessionId, - downloadManager = FetchDownloadManager(requireContext().applicationContext, DownloadService::class), - onNeedToRequestPermissions = { permissions -> - requestPermissions(permissions, REQUEST_CODE_DOWNLOAD_PERMISSIONS) - }), - owner = this, - view = view - ) - - appLinksFeature.set( - feature = AppLinksFeature( - requireContext(), - sessionManager = sessionManager, - sessionId = customTabSessionId, - interceptLinkClicks = true, - fragmentManager = requireFragmentManager() - ), - owner = this, - view = view - ) - - promptsFeature.set( - feature = PromptFeature( - fragment = this, - sessionManager = sessionManager, - sessionId = customTabSessionId, - fragmentManager = requireFragmentManager(), - onNeedToRequestPermissions = { permissions -> - requestPermissions(permissions, REQUEST_CODE_PROMPT_PERMISSIONS) - }), - owner = this, - view = view - ) - - sessionFeature.set( - feature = SessionFeature( - sessionManager, - SessionUseCases(sessionManager), - view.engineView, - customTabSessionId - ), - owner = this, - view = view - ) - - val accentHighContrastColor = ThemeManager.resolveAttribute(R.attr.accentHighContrast, requireContext()) - - sitePermissionsFeature.set( - feature = SitePermissionsFeature( - context = requireContext(), - sessionManager = sessionManager, - fragmentManager = requireFragmentManager(), - promptsStyling = SitePermissionsFeature.PromptsStyling( - gravity = getAppropriateLayoutGravity(), - shouldWidthMatchParent = true, - positiveButtonBackgroundColor = accentHighContrastColor, - positiveButtonTextColor = R.color.photonWhite - ), - sessionId = customTabSessionId - ) { permissions -> - requestPermissions(permissions, REQUEST_CODE_APP_PERMISSIONS) - }, - owner = this, - view = view - ) - - fullScreenFeature.set( - feature = FullScreenFeature( - sessionManager, - SessionUseCases(sessionManager), - customTabSessionId - ) { inFullScreen -> - if (inFullScreen) { - FenixSnackbar.make(view.rootView, Snackbar.LENGTH_SHORT) - .setText(getString(R.string.full_screen_notification)) - .show() - activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE - activity?.enterToImmersiveMode() - toolbar.visibility = View.GONE - nestedScrollQuickAction.visibility = View.GONE - } else { - activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER - activity?.exitImmersiveModeIfNeeded() - (activity as HomeActivity).let { activity: HomeActivity -> - ThemeManager.applyStatusBarTheme( - activity.window, - activity.themeManager, - activity + FenixSnackbarDelegate( + view, + if (getSessionById()?.isCustomTabSession() == true) null else nestedScrollQuickAction ) - } - toolbar.visibility = View.VISIBLE - nestedScrollQuickAction.visibility = View.VISIBLE - } - view.swipeRefresh.apply { - val (topMargin, bottomMargin) = if (inFullScreen) 0 to 0 else getEngineMargins() - (layoutParams as CoordinatorLayout.LayoutParams).setMargins(0, topMargin, 0, bottomMargin) - } - }, - owner = this, - view = view - ) + ), + view.engineView + ), + owner = this, + view = view + ) - if (FeatureFlags.pullToRefreshEnabled) { - val primaryTextColor = ThemeManager.resolveAttribute(R.attr.primaryText, requireContext()) - view.swipeRefresh.setColorSchemeColors(primaryTextColor) - swipeRefreshFeature.set( - feature = SwipeRefreshFeature( - requireComponents.core.sessionManager, - requireComponents.useCases.sessionUseCases.reload, - view.swipeRefresh, + downloadsFeature.set( + feature = DownloadsFeature( + requireContext().applicationContext, + sessionManager = sessionManager, + fragmentManager = childFragmentManager, + sessionId = customTabSessionId, + downloadManager = FetchDownloadManager(requireContext().applicationContext, DownloadService::class), + onNeedToRequestPermissions = { permissions -> + requestPermissions(permissions, REQUEST_CODE_DOWNLOAD_PERMISSIONS) + }), + owner = this, + view = view + ) + + appLinksFeature.set( + feature = AppLinksFeature( + requireContext(), + sessionManager = sessionManager, + sessionId = customTabSessionId, + interceptLinkClicks = true, + fragmentManager = requireFragmentManager() + ), + owner = this, + view = view + ) + + promptsFeature.set( + feature = PromptFeature( + fragment = this, + sessionManager = sessionManager, + sessionId = customTabSessionId, + fragmentManager = requireFragmentManager(), + onNeedToRequestPermissions = { permissions -> + requestPermissions(permissions, REQUEST_CODE_PROMPT_PERMISSIONS) + }), + owner = this, + view = view + ) + + sessionFeature.set( + feature = SessionFeature( + sessionManager, + SessionUseCases(sessionManager), + view.engineView, customTabSessionId ), owner = this, view = view ) - } else { - // Disable pull to refresh - view.swipeRefresh.setOnChildScrollUpCallback { _, _ -> true } + + val accentHighContrastColor = ThemeManager.resolveAttribute(R.attr.accentHighContrast, requireContext()) + + sitePermissionsFeature.set( + feature = SitePermissionsFeature( + context = requireContext(), + sessionManager = sessionManager, + fragmentManager = requireFragmentManager(), + promptsStyling = SitePermissionsFeature.PromptsStyling( + gravity = getAppropriateLayoutGravity(), + shouldWidthMatchParent = true, + positiveButtonBackgroundColor = accentHighContrastColor, + positiveButtonTextColor = R.color.photonWhite + ), + sessionId = customTabSessionId + ) { permissions -> + requestPermissions(permissions, REQUEST_CODE_APP_PERMISSIONS) + }, + owner = this, + view = view + ) + + fullScreenFeature.set( + feature = FullScreenFeature( + sessionManager, + SessionUseCases(sessionManager), + customTabSessionId + ) { inFullScreen -> + if (inFullScreen) { + FenixSnackbar.make(view.rootView, Snackbar.LENGTH_SHORT) + .setText(getString(R.string.full_screen_notification)) + .show() + activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE + activity?.enterToImmersiveMode() + toolbar.visibility = View.GONE + nestedScrollQuickAction.visibility = View.GONE + } else { + activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER + activity?.exitImmersiveModeIfNeeded() + (activity as HomeActivity).let { activity: HomeActivity -> + ThemeManager.applyStatusBarTheme( + activity.window, + activity.themeManager, + activity + ) + } + toolbar.visibility = View.VISIBLE + nestedScrollQuickAction.visibility = View.VISIBLE + } + view.swipeRefresh.apply { + val (topMargin, bottomMargin) = if (inFullScreen) 0 to 0 else getEngineMargins() + (layoutParams as CoordinatorLayout.LayoutParams).setMargins(0, topMargin, 0, bottomMargin) + } + }, + owner = this, + view = view + ) + + @Suppress("ConstantConditionIf") + if (FeatureFlags.pullToRefreshEnabled) { + val primaryTextColor = ThemeManager.resolveAttribute(R.attr.primaryText, requireContext()) + view.swipeRefresh.setColorSchemeColors(primaryTextColor) + swipeRefreshFeature.set( + feature = SwipeRefreshFeature( + requireComponents.core.sessionManager, + requireComponents.useCases.sessionUseCases.reload, + view.swipeRefresh, + customTabSessionId + ), + owner = this, + view = view + ) + } else { + // Disable pull to refresh + view.swipeRefresh.setOnChildScrollUpCallback { _, _ -> true } + } + + (activity as HomeActivity).updateThemeForSession(session) } } + @CallSuper + override fun onSessionSelected(session: Session) { + super.onSessionSelected(session) + if (!browserInitialized) { + // Initializing a new coroutineScope to avoid ConcurrentModificationException in ObserverRegistry + // This will be removed when ObserverRegistry is deprecated by browser-state. + initUIJob = MainScope().launch { + view?.let { + browserInitialized = initializeUI(it) != null + } + } + } + } + + @CallSuper + override fun onStart() { + super.onStart() + requireComponents.core.sessionManager.register(this, this, autoPause = true) + } + @CallSuper override fun onResume() { super.onResume() - val session = getSessionById() ?: return val components = requireComponents val preferredColorScheme = components.core.getPreferredColorScheme() @@ -343,20 +373,23 @@ abstract class BaseBrowserFragment : Fragment(), BackHandler { components.core.engine.settings.preferredColorScheme = preferredColorScheme components.useCases.sessionUseCases.reload() } - (activity as HomeActivity).updateThemeForSession(session) (activity as AppCompatActivity).supportActionBar?.hide() assignSitePermissionsRules() } - /** - * Exits full screen mode. - */ + @CallSuper final override fun onPause() { super.onPause() fullScreenFeature.onBackPressed() } + @CallSuper + override fun onStop() { + super.onStop() + initUIJob?.cancel() + } + @CallSuper override fun onBackPressed(): Boolean { return findInPageIntegration.onBackPressed() || @@ -480,8 +513,9 @@ abstract class BaseBrowserFragment : Fragment(), BackHandler { */ protected fun getSessionById(): Session? { val sessionManager = context?.components?.core?.sessionManager ?: return null - return if (customTabSessionId != null) { - sessionManager.findSessionById(customTabSessionId!!) + val localCustomTabId = customTabSessionId + return if (localCustomTabId != null) { + sessionManager.findSessionById(localCustomTabId) } else { sessionManager.selectedSession } diff --git a/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt index 9493010de..61b78d2a7 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt @@ -14,7 +14,6 @@ import android.widget.RadioButton import androidx.core.content.ContextCompat import androidx.lifecycle.Observer import androidx.lifecycle.lifecycleScope -import androidx.navigation.fragment.NavHostFragment.findNavController import androidx.navigation.fragment.findNavController import androidx.transition.TransitionInflater import com.google.android.material.snackbar.Snackbar @@ -30,7 +29,6 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import mozilla.appservices.places.BookmarkRoot import mozilla.components.browser.session.Session -import mozilla.components.browser.session.SessionManager import mozilla.components.feature.readerview.ReaderViewFeature import mozilla.components.feature.session.ThumbnailsFeature import mozilla.components.lib.state.ext.consumeFrom @@ -59,6 +57,8 @@ import java.net.URL /** * Fragment used for browsing the web within the main app and external apps. */ +@ObsoleteCoroutinesApi +@ExperimentalCoroutinesApi @Suppress("TooManyFunctions") class BrowserFragment : BaseBrowserFragment(), BackHandler { private lateinit var quickActionSheetView: QuickActionSheetView @@ -91,17 +91,12 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler { return view } - @Suppress("LongMethod", "ComplexMethod") - @ObsoleteCoroutinesApi - @ExperimentalCoroutinesApi - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - + override fun initializeUI(view: View): Session? { val sessionManager = requireComponents.core.sessionManager - getSessionById()?.let { - quickActionSheetView = - QuickActionSheetView(view.nestedScrollQuickAction, browserInteractor) + return super.initializeUI(view)?.also { session -> + + quickActionSheetView = QuickActionSheetView(view.nestedScrollQuickAction, browserInteractor) customTabSessionId?.let { customTabSessionId -> customTabsIntegration.set( @@ -119,57 +114,58 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler { view = view) } + thumbnailsFeature.set( + feature = ThumbnailsFeature( + requireContext(), + view.engineView, + requireComponents.core.sessionManager + ), + owner = this, + view = view + ) + + readerViewFeature.set( + feature = ReaderViewFeature( + requireContext(), + requireComponents.core.engine, + requireComponents.core.sessionManager, + view.readerViewControlsBar + ) { available -> + if (available) { + requireComponents.analytics.metrics.track(Event.ReaderModeAvailable) + } + + browserStore.apply { + dispatch(QuickActionSheetAction.ReadableStateChange(available)) + dispatch( + QuickActionSheetAction.ReaderActiveStateChange( + sessionManager.selectedSession?.readerMode ?: false + ) + ) + } + }, + owner = this, + view = view + ) + + if ((activity as HomeActivity).browsingModeManager.isPrivate) { + // We need to update styles for private mode programmatically for now: + // https://github.com/mozilla-mobile/android-components/issues/3400 + themeReaderViewControlsForPrivateMode(view.readerViewControlsBar) + } + + updateBookmarkState(session) + consumeFrom(browserStore) { quickActionSheetView.update(it) browserToolbarView.update(it) } } - - thumbnailsFeature.set( - feature = ThumbnailsFeature( - requireContext(), - view.engineView, - requireComponents.core.sessionManager - ), - owner = this, - view = view - ) - - readerViewFeature.set( - feature = ReaderViewFeature( - requireContext(), - requireComponents.core.engine, - requireComponents.core.sessionManager, - view.readerViewControlsBar - ) { available -> - if (available) { - requireComponents.analytics.metrics.track(Event.ReaderModeAvailable) - } - - browserStore.apply { - dispatch(QuickActionSheetAction.ReadableStateChange(available)) - dispatch( - QuickActionSheetAction.ReaderActiveStateChange( - sessionManager.selectedSession?.readerMode ?: false - ) - ) - } - }, - owner = this, - view = view - ) - - if ((activity as HomeActivity).browsingModeManager.isPrivate) { - // We need to update styles for private mode programmatically for now: - // https://github.com/mozilla-mobile/android-components/issues/3400 - themeReaderViewControlsForPrivateMode(view.readerViewControlsBar) - } } override fun onStart() { super.onStart() subscribeToSession() - subscribeToSessions() subscribeToTabCollections() } @@ -177,11 +173,6 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler { super.onResume() requireComponents.core.tabCollectionStorage.register(collectionStorageObserver, this) - - getSessionById()?.let { updateBookmarkState(it) } - - // See #4387 for why we're popping here - if (getSessionById() == null) findNavController(this).popBackStack(R.id.homeFragment, false) } override fun onBackPressed(): Boolean { @@ -332,14 +323,9 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler { getSessionById()?.register(observer, this, autoPause = true) } - private fun subscribeToSessions() { - val observer = object : SessionManager.Observer { - override fun onSessionSelected(session: Session) { - (activity as HomeActivity).updateThemeForSession(session) - updateBookmarkState(session) - } - } - requireComponents.core.sessionManager.register(observer, this, autoPause = true) + override fun onSessionSelected(session: Session) { + super.onSessionSelected(session) + updateBookmarkState(session) } private suspend fun findBookmarkedURL(session: Session?): Boolean { diff --git a/app/src/main/java/org/mozilla/fenix/collections/CreateCollectionFragment.kt b/app/src/main/java/org/mozilla/fenix/collections/CreateCollectionFragment.kt index 7664ff1f8..369f58d27 100644 --- a/app/src/main/java/org/mozilla/fenix/collections/CreateCollectionFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/collections/CreateCollectionFragment.kt @@ -10,7 +10,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.DialogFragment -import androidx.lifecycle.ViewModelProvider +import androidx.fragment.app.activityViewModels import androidx.lifecycle.lifecycleScope import kotlinx.android.synthetic.main.fragment_create_collection.view.* import kotlinx.coroutines.Dispatchers @@ -28,7 +28,7 @@ import org.mozilla.fenix.mvi.getManagedEmitter class CreateCollectionFragment : DialogFragment() { private lateinit var collectionCreationComponent: CollectionCreationComponent - private lateinit var viewModel: CreateCollectionViewModel + private val viewModel: CreateCollectionViewModel by activityViewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -43,10 +43,6 @@ class CreateCollectionFragment : DialogFragment() { ): View? { val view = inflater.inflate(R.layout.fragment_create_collection, container, false) - viewModel = activity!!.run { - ViewModelProvider(this).get(CreateCollectionViewModel::class.java) - } - collectionCreationComponent = CollectionCreationComponent( view.createCollectionWrapper, ActionBusFactory.get(this), diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt index 553ba4b2b..757f673c6 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt @@ -10,6 +10,8 @@ import android.content.Intent import androidx.core.widget.NestedScrollView import androidx.navigation.NavController import com.google.android.material.bottomsheet.BottomSheetBehavior +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.ObsoleteCoroutinesApi import mozilla.components.browser.session.Session import mozilla.components.concept.engine.EngineView import org.mozilla.fenix.BrowsingModeManager @@ -59,6 +61,8 @@ class DefaultBrowserToolbarController( ) } + @ExperimentalCoroutinesApi + @ObsoleteCoroutinesApi @SuppressWarnings("ComplexMethod") override fun handleToolbarItemInteraction(item: ToolbarMenu.Item) { val sessionUseCases = context.components.useCases.sessionUseCases diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt index 56f72309c..f1425e5b5 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -19,11 +19,11 @@ import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.PARENT_ID import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleObserver import androidx.lifecycle.Observer import androidx.lifecycle.OnLifecycleEvent -import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.FragmentNavigator import androidx.navigation.fragment.NavHostFragment.findNavController @@ -204,15 +204,12 @@ class HomeFragment : Fragment(), AccountObserver { } private fun restoreLayoutState() { - val homeViewModel = activity?.run { - ViewModelProvider(this).get(HomeScreenViewModel::class.java) - } - - homeViewModel?.layoutManagerState?.also { parcelable -> + val homeViewModel: HomeScreenViewModel by activityViewModels() + homeViewModel.layoutManagerState?.also { parcelable -> sessionControlComponent.view.layoutManager?.onRestoreInstanceState(parcelable) } - homeLayout?.progress = homeViewModel?.motionLayoutProgress ?: 0F - homeViewModel?.layoutManagerState = null + homeLayout?.progress = homeViewModel.motionLayoutProgress + homeViewModel.layoutManagerState = null } @SuppressWarnings("LongMethod") @@ -555,12 +552,10 @@ class HomeFragment : Fragment(), AccountObserver { override fun onPause() { invokePendingDeleteJobs() super.onPause() - val homeViewModel = activity?.run { - ViewModelProvider(this).get(HomeScreenViewModel::class.java) - } - homeViewModel?.layoutManagerState = + val homeViewModel: HomeScreenViewModel by activityViewModels() + homeViewModel.layoutManagerState = sessionControlComponent.view.layoutManager?.onSaveInstanceState() - homeViewModel?.motionLayoutProgress = homeLayout?.progress ?: 0F + homeViewModel.motionLayoutProgress = homeLayout?.progress ?: 0F } private fun setupHomeMenu() { @@ -691,21 +686,18 @@ class HomeFragment : Fragment(), AccountObserver { val tabs = getListOfSessions().toTabs() - val viewModel = activity?.run { - ViewModelProvider(this).get(CreateCollectionViewModel::class.java) - } - viewModel?.tabs = tabs + val viewModel: CreateCollectionViewModel by activityViewModels() + viewModel.tabs = tabs val selectedTabs = tabs.find { tab -> tab.sessionId == selectedTabId } ?: if (tabs.size == 1) tabs[0] else null val selectedSet = if (selectedTabs == null) mutableSetOf() else mutableSetOf(selectedTabs) - viewModel?.selectedTabs = selectedSet - viewModel?.tabCollections = - requireComponents.core.tabCollectionStorage.cachedTabCollections.reversed() - viewModel?.selectedTabCollection = selectedTabCollection - viewModel?.saveCollectionStep = - step ?: viewModel?.getStepForTabsAndCollectionSize() ?: SaveCollectionStep.SelectTabs - viewModel?.previousFragmentId = R.id.homeFragment + viewModel.selectedTabs = selectedSet + viewModel.tabCollections = requireComponents.core.tabCollectionStorage.cachedTabCollections.reversed() + viewModel.selectedTabCollection = selectedTabCollection + viewModel.saveCollectionStep = + step ?: viewModel.getStepForTabsAndCollectionSize() + viewModel.previousFragmentId = R.id.homeFragment // Only register the observer right before moving to collection creation requireComponents.core.tabCollectionStorage.register(collectionStorageObserver, this) 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 fe715f349..0637814d0 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/DeleteBrowsingDataFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/DeleteBrowsingDataFragment.kt @@ -14,6 +14,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import androidx.lifecycle.Observer import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController import kotlinx.android.synthetic.main.fragment_delete_browsing_data.* import kotlinx.android.synthetic.main.fragment_delete_browsing_data.view.* import kotlinx.coroutines.Dispatchers @@ -114,14 +115,15 @@ class DeleteBrowsingDataFragment : Fragment() { } } - fun startDeletion() { + private fun startDeletion() { progress_bar.visibility = View.VISIBLE delete_browsing_data_wrapper.isEnabled = false delete_browsing_data_wrapper.isClickable = false delete_browsing_data_wrapper.alpha = DISABLED_ALPHA } - fun finishDeletion() { + private fun finishDeletion() { + val popAfter = open_tabs_item.isChecked progress_bar.visibility = View.GONE delete_browsing_data_wrapper.isEnabled = true delete_browsing_data_wrapper.isClickable = true @@ -138,6 +140,10 @@ class DeleteBrowsingDataFragment : Fragment() { FenixSnackbar.make(view!!, FenixSnackbar.LENGTH_SHORT) .setText(resources.getString(R.string.preferences_delete_browsing_data_snackbar)) .show() + + if (popAfter) viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Main) { + findNavController().popBackStack(R.id.homeFragment, false) + } } private fun updateDeleteButton() { 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 6dff18250..f798384a7 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 @@ -26,6 +26,8 @@ import androidx.navigation.fragment.NavHostFragment.findNavController import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.ObsoleteCoroutinesApi import kotlinx.coroutines.launch import mozilla.components.browser.session.Session import mozilla.components.feature.sitepermissions.SitePermissions @@ -48,6 +50,7 @@ import com.google.android.material.R as MaterialR private const val REQUEST_CODE_QUICK_SETTINGS_PERMISSIONS = 4 +@ObsoleteCoroutinesApi @SuppressWarnings("TooManyFunctions") class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() { private val safeArguments get() = requireNotNull(arguments) @@ -167,6 +170,8 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() { } } + @ExperimentalCoroutinesApi + @ObsoleteCoroutinesApi override fun onResume() { super.onResume() getAutoDisposeObservable()