diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 74faca1db..a2211fc1e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -25,7 +25,8 @@ tools:ignore="UnusedAttribute"> + android:windowSoftInputMode="adjustResize" + android:configChanges="keyboard|keyboardHidden|mcc|mnc|orientation|screenSize|locale|layoutDirection|smallestScreenSize|screenLayout"> diff --git a/app/src/main/java/org/mozilla/fenix/collections/CollectionCreationComponent.kt b/app/src/main/java/org/mozilla/fenix/collections/CollectionCreationComponent.kt index c80be417d..7c590dd2a 100644 --- a/app/src/main/java/org/mozilla/fenix/collections/CollectionCreationComponent.kt +++ b/app/src/main/java/org/mozilla/fenix/collections/CollectionCreationComponent.kt @@ -67,9 +67,9 @@ class CollectionCreationComponent( override fun initView() = CollectionCreationUIView(container, actionEmitter, changesObservable) override fun render(): Observable = - ViewModelProvider(owner, CollectionCreationViewModel.Factory(initialState, changesObservable)).get( + ViewModelProvider(owner, CollectionCreationViewModel.Factory(initialState)).get( CollectionCreationViewModel::class.java - ).render(uiView) + ).render(changesObservable, uiView) init { render() @@ -77,22 +77,19 @@ class CollectionCreationComponent( } class CollectionCreationViewModel( - initialState: CollectionCreationState, - changesObservable: Observable + initialState: CollectionCreationState ) : UIComponentViewModel( initialState, - changesObservable, reducer ) { class Factory( - private val initialState: CollectionCreationState, - private val changesObservable: Observable + private val initialState: CollectionCreationState ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create(modelClass: Class): T = - CollectionCreationViewModel(initialState, changesObservable) as T + CollectionCreationViewModel(initialState) as T } companion object { diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarComponent.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarComponent.kt index 3368d14df..8b2d376f5 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarComponent.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarComponent.kt @@ -53,7 +53,7 @@ class ToolbarComponent( override fun render(): Observable = ViewModelProviders.of(owner, ToolbarViewModel.Factory(initialState, changesObservable)) - .get(ToolbarViewModel::class.java).render(uiView) + .get(ToolbarViewModel::class.java).render(changesObservable, uiView) init { render() @@ -99,8 +99,8 @@ sealed class SearchChange : Change { data class SearchShortcutEngineSelected(val engine: SearchEngine) : SearchChange() } -class ToolbarViewModel(initialState: SearchState, changesObservable: Observable) : - UIComponentViewModel(initialState, changesObservable, reducer) { +class ToolbarViewModel(initialState: SearchState) : + UIComponentViewModel(initialState, reducer) { class Factory( private val initialState: SearchState, @@ -108,7 +108,7 @@ class ToolbarViewModel(initialState: SearchState, changesObservable: Observable< ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create(modelClass: Class): T = - ToolbarViewModel(initialState, changesObservable) as T + ToolbarViewModel(initialState) as T } companion object { diff --git a/app/src/main/java/org/mozilla/fenix/exceptions/ExceptionsComponent.kt b/app/src/main/java/org/mozilla/fenix/exceptions/ExceptionsComponent.kt index aff226da9..52ecd5702 100644 --- a/app/src/main/java/org/mozilla/fenix/exceptions/ExceptionsComponent.kt +++ b/app/src/main/java/org/mozilla/fenix/exceptions/ExceptionsComponent.kt @@ -33,8 +33,8 @@ class ExceptionsComponent( ) { override fun render(): Observable = - ViewModelProviders.of(owner, ExceptionsViewModel.Factory(initialState, changesObservable)) - .get(ExceptionsViewModel::class.java).render(uiView) + ViewModelProviders.of(owner, ExceptionsViewModel.Factory(initialState)) + .get(ExceptionsViewModel::class.java).render(changesObservable, uiView) override fun initView() = ExceptionsUIView(container, actionEmitter, changesObservable) @@ -56,20 +56,18 @@ sealed class ExceptionsChange : Change { data class Change(val list: List) : ExceptionsChange() } -class ExceptionsViewModel(initialState: ExceptionsState, changesObservable: Observable) : +class ExceptionsViewModel(initialState: ExceptionsState) : UIComponentViewModel( initialState, - changesObservable, reducer ) { class Factory( - private val initialState: ExceptionsState, - private val changesObservable: Observable + private val initialState: ExceptionsState ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create(modelClass: Class): T = - ExceptionsViewModel(initialState, changesObservable) as T + ExceptionsViewModel(initialState) as T } companion object { 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 963bab961..62a8ffccd 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -155,33 +155,37 @@ class HomeFragment : Fragment(), CoroutineScope { privateBrowsingButton.setOnClickListener { val browsingModeManager = (activity as HomeActivity).browsingModeManager - browsingModeManager.mode = when (browsingModeManager.mode) { + val newMode = when (browsingModeManager.mode) { BrowsingModeManager.Mode.Normal -> BrowsingModeManager.Mode.Private BrowsingModeManager.Mode.Private -> BrowsingModeManager.Mode.Normal } + + val mode = if (newMode == BrowsingModeManager.Mode.Private) Mode.Private else Mode.Normal + getManagedEmitter().onNext(SessionControlChange.ModeChange(mode)) + + browsingModeManager.mode = newMode } // We need the shadow to be above the components. homeDividerShadow.bringToFront() } - override fun onSaveInstanceState(outState: Bundle) { - super.onSaveInstanceState(outState) - // This can get called before onCreateView, before the component is defined - view?.let { - val state = sessionControlComponent.stateObservable.blockingFirst() - val modeInt = if (state.mode is Mode.Private) 0 else 1 - outState.putInt(KEY_MODE, modeInt) - } - } - override fun onViewStateRestored(savedInstanceState: Bundle?) { super.onViewStateRestored(savedInstanceState) if (savedInstanceState != null) { - emitSessionChanges() - val mode = if (savedInstanceState.getInt(KEY_MODE) == 0) Mode.Private else Mode.Normal getManagedEmitter().onNext( - SessionControlChange.ModeChange(mode) + SessionControlChange.TabsChange( + (savedInstanceState.getParcelableArrayList( + KEY_TABS + ) ?: arrayListOf()).toList() + ) + ) + getManagedEmitter().onNext( + SessionControlChange.CollectionsChange( + (savedInstanceState.getParcelableArrayList( + KEY_COLLECTIONS + ) ?: arrayListOf()).toList() + ) ) } } @@ -210,6 +214,9 @@ class HomeFragment : Fragment(), CoroutineScope { } } + val mode = if ((activity as HomeActivity).browsingModeManager.isPrivate) Mode.Private else Mode.Normal + getManagedEmitter().onNext(SessionControlChange.ModeChange(mode)) + emitSessionChanges() sessionObserver = subscribeToSessions() } diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlComponent.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlComponent.kt index 9f692aff6..71fadacab 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlComponent.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlComponent.kt @@ -42,9 +42,9 @@ class SessionControlComponent( get() = uiView.view as RecyclerView override fun render(): Observable { - viewModel = ViewModelProviders.of(owner, SessionControlViewModel.Factory(initialState, changesObservable)) + viewModel = ViewModelProviders.of(owner, SessionControlViewModel.Factory(initialState)) .get(SessionControlViewModel::class.java) - return viewModel.render(uiView) + return viewModel.render(changesObservable, uiView) } init { @@ -123,20 +123,18 @@ sealed class SessionControlChange : Change { data class CollectionsChange(val collections: List) : SessionControlChange() } -class SessionControlViewModel(initialState: SessionControlState, changesObservable: Observable) : +class SessionControlViewModel(initialState: SessionControlState) : UIComponentViewModel( initialState, - changesObservable, reducer ) { class Factory( - private val initialState: SessionControlState, - private val changesObservable: Observable + private val initialState: SessionControlState ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create(modelClass: Class): T = - SessionControlViewModel(initialState, changesObservable) as T + SessionControlViewModel(initialState) as T } companion object { diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkComponent.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkComponent.kt index 5b9bd010d..3a929b71f 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkComponent.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkComponent.kt @@ -39,8 +39,8 @@ class BookmarkComponent( override fun render(): Observable { return ViewModelProvider( owner, - BookmarkViewModel.Factory(initialState, changesObservable) - ).get(BookmarkViewModel::class.java).render(uiView) + BookmarkViewModel.Factory(initialState) + ).get(BookmarkViewModel::class.java).render(changesObservable, uiView) } init { @@ -81,16 +81,15 @@ operator fun BookmarkNode.contains(item: BookmarkNode): Boolean { return children?.contains(item) ?: false } -class BookmarkViewModel(initialState: BookmarkState, changesObservable: Observable) : - UIComponentViewModel(initialState, changesObservable, reducer) { +class BookmarkViewModel(initialState: BookmarkState) : + UIComponentViewModel(initialState, reducer) { class Factory( - private val initialState: BookmarkState, - private val changesObservable: Observable + private val initialState: BookmarkState ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create(modelClass: Class): T = - BookmarkViewModel(initialState, changesObservable) as T + BookmarkViewModel(initialState) as T } companion object { diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/SignInComponent.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/SignInComponent.kt index 2ac3c8e46..71b9b5aa3 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/SignInComponent.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/SignInComponent.kt @@ -35,8 +35,8 @@ class SignInComponent( override fun render(): Observable = ViewModelProvider( owner, - SignInViewModel.Factory(initialState, changesObservable) - ).get(SignInViewModel::class.java).render(uiView) + SignInViewModel.Factory(initialState) + ).get(SignInViewModel::class.java).render(changesObservable, uiView) init { render() @@ -54,18 +54,17 @@ sealed class SignInChange : Change { object SignedOut : SignInChange() } -class SignInViewModel(initialState: SignInState, changesObservable: Observable) : +class SignInViewModel(initialState: SignInState) : UIComponentViewModel( - initialState, changesObservable, reducer + initialState, reducer ) { class Factory( - private val initialState: SignInState, - private val changesObservable: Observable + private val initialState: SignInState ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create(modelClass: Class): T = - SignInViewModel(initialState, changesObservable) as T + SignInViewModel(initialState) as T } companion object { diff --git a/app/src/main/java/org/mozilla/fenix/library/history/HistoryComponent.kt b/app/src/main/java/org/mozilla/fenix/library/history/HistoryComponent.kt index 09be4fbb4..18680f8e3 100644 --- a/app/src/main/java/org/mozilla/fenix/library/history/HistoryComponent.kt +++ b/app/src/main/java/org/mozilla/fenix/library/history/HistoryComponent.kt @@ -36,8 +36,8 @@ class HistoryComponent( override fun render(): Observable = ViewModelProvider( owner, - HistoryViewModel.Factory(initialState, changesObservable) - ).get(HistoryViewModel::class.java).render(uiView) + HistoryViewModel.Factory(initialState) + ).get(HistoryViewModel::class.java).render(changesObservable, uiView) init { render() @@ -74,16 +74,15 @@ sealed class HistoryChange : Change { data class RemoveItemForRemoval(val item: HistoryItem) : HistoryChange() } -class HistoryViewModel(initialState: HistoryState, changesObservable: Observable) : - UIComponentViewModel(initialState, changesObservable, reducer) { +class HistoryViewModel(initialState: HistoryState) : + UIComponentViewModel(initialState, reducer) { class Factory( - private val initialState: HistoryState, - private val changesObservable: Observable + private val initialState: HistoryState ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create(modelClass: Class): T = - HistoryViewModel(initialState, changesObservable) as T + HistoryViewModel(initialState) as T } companion object { diff --git a/app/src/main/java/org/mozilla/fenix/quickactionsheet/QuickActionComponent.kt b/app/src/main/java/org/mozilla/fenix/quickactionsheet/QuickActionComponent.kt index cbf14dc9f..3ec185fb3 100644 --- a/app/src/main/java/org/mozilla/fenix/quickactionsheet/QuickActionComponent.kt +++ b/app/src/main/java/org/mozilla/fenix/quickactionsheet/QuickActionComponent.kt @@ -39,8 +39,8 @@ class QuickActionComponent( override fun render(): Observable = ViewModelProvider( owner, - QuickActionViewModel.Factory(initialState, changesObservable) - ).get(QuickActionViewModel::class.java).render(uiView) + QuickActionViewModel.Factory(initialState) + ).get(QuickActionViewModel::class.java).render(changesObservable, uiView) init { render() @@ -71,20 +71,18 @@ sealed class QuickActionChange : Change { object BounceNeededChange : QuickActionChange() } -class QuickActionViewModel(initialState: QuickActionState, changesObservable: Observable) : +class QuickActionViewModel(initialState: QuickActionState) : UIComponentViewModel( initialState, - changesObservable, reducer ) { class Factory( - private val initialState: QuickActionState, - private val changesObservable: Observable + private val initialState: QuickActionState ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create(modelClass: Class): T = - QuickActionViewModel(initialState, changesObservable) as T + QuickActionViewModel(initialState) as T } companion object { diff --git a/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarComponent.kt b/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarComponent.kt index 81099c02f..4c8d2bbcb 100644 --- a/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarComponent.kt +++ b/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarComponent.kt @@ -51,28 +51,26 @@ class AwesomeBarComponent( override fun initView() = AwesomeBarUIView(container, actionEmitter, changesObservable) override fun render(): Observable = - ViewModelProviders.of(owner, AwesomeBarViewModel.Factory(initialState, changesObservable)) - .get(AwesomeBarViewModel::class.java).render(uiView) + ViewModelProviders.of(owner, AwesomeBarViewModel.Factory(initialState)) + .get(AwesomeBarViewModel::class.java).render(changesObservable, uiView) init { render() } } -class AwesomeBarViewModel(initialState: AwesomeBarState, changesObservable: Observable) : +class AwesomeBarViewModel(initialState: AwesomeBarState) : UIComponentViewModel( initialState, - changesObservable, reducer ) { class Factory( - private val initialState: AwesomeBarState, - private val changesObservable: Observable + private val initialState: AwesomeBarState ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create(modelClass: Class): T = - AwesomeBarViewModel(initialState, changesObservable) as T + AwesomeBarViewModel(initialState) as T } companion object { diff --git a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsComponent.kt b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsComponent.kt index 26d4eb2db..fa9e7c2b2 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsComponent.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsComponent.kt @@ -40,9 +40,9 @@ class QuickSettingsComponent( } override fun render(): Observable = - ViewModelProvider(owner, QuickSettingsViewModel.Factory(initialState, changesObservable)).get( + ViewModelProvider(owner, QuickSettingsViewModel.Factory(initialState)).get( QuickSettingsViewModel::class.java - ).render(uiView) + ).render(changesObservable, uiView) init { render() @@ -120,20 +120,18 @@ sealed class QuickSettingsChange : Change { data class Stored(val phoneFeature: PhoneFeature, val sitePermissions: SitePermissions?) : QuickSettingsChange() } -class QuickSettingsViewModel(initialState: QuickSettingsState, changesObservable: Observable) : +class QuickSettingsViewModel(initialState: QuickSettingsState) : UIComponentViewModel( initialState, - changesObservable, reducer ) { class Factory( - private val initialState: QuickSettingsState, - private val changesObservable: Observable + private val initialState: QuickSettingsState ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create(modelClass: Class): T = - QuickSettingsViewModel(initialState, changesObservable) as T + QuickSettingsViewModel(initialState) as T } companion object { diff --git a/architecture/src/main/java/org/mozilla/fenix/mvi/UIComponent.kt b/architecture/src/main/java/org/mozilla/fenix/mvi/UIComponent.kt index 85eadf47c..60506b51c 100644 --- a/architecture/src/main/java/org/mozilla/fenix/mvi/UIComponent.kt +++ b/architecture/src/main/java/org/mozilla/fenix/mvi/UIComponent.kt @@ -28,32 +28,33 @@ abstract class UIComponent( } open class UIComponentViewModel( - private val initialState: S, - val changesObservable: Observable, - reducer: Reducer + initialState: S, + private val reducer: Reducer ) : ViewModel() { - private val statesObservable: Observable = internalRender(reducer) + private var currentState: S = initialState private var statesDisposable: Disposable? = null /** * Render the ViewState to the View through the Reducer */ - fun render(uiView: UIView): Observable { + fun render(changesObservable: Observable, uiView: UIView): Observable { + val statesObservable = internalRender(changesObservable, reducer) statesDisposable = statesObservable .subscribe(uiView.updateView()) return statesObservable } @Suppress("MemberVisibilityCanBePrivate") - protected fun internalRender(reducer: Reducer): Observable = + protected fun internalRender(changesObservable: Observable, reducer: Reducer): Observable = changesObservable - .scan(initialState, reducer) + .scan(currentState, reducer) .distinctUntilChanged() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .replay(1) .autoConnect(0) + .doOnNext { currentState = it } override fun onCleared() { super.onCleared()