mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-22 09:25:49 +03:00
Fragment factory: start including the new version with FragmentFactory [WIP]
This commit is contained in:
parent
cd1a964067
commit
3013d67c16
12 changed files with 164 additions and 27 deletions
|
@ -217,6 +217,7 @@ android {
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
def epoxy_version = '3.8.0'
|
def epoxy_version = '3.8.0'
|
||||||
|
def fragment_version = '1.2.0-rc01'
|
||||||
def arrow_version = "0.8.2"
|
def arrow_version = "0.8.2"
|
||||||
def coroutines_version = "1.3.2"
|
def coroutines_version = "1.3.2"
|
||||||
def markwon_version = '4.1.2'
|
def markwon_version = '4.1.2'
|
||||||
|
@ -234,6 +235,8 @@ dependencies {
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||||
|
|
||||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||||
|
implementation "androidx.fragment:fragment:$fragment_version"
|
||||||
|
implementation "androidx.fragment:fragment-ktx:$fragment_version"
|
||||||
//Do not use beta2 at the moment, as it breaks things
|
//Do not use beta2 at the moment, as it breaks things
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta1'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta1'
|
||||||
implementation 'androidx.core:core-ktx:1.1.0'
|
implementation 'androidx.core:core-ktx:1.1.0'
|
||||||
|
|
28
vector/src/main/java/im/vector/riotx/core/di/FragmentKey.kt
Normal file
28
vector/src/main/java/im/vector/riotx/core/di/FragmentKey.kt
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.riotx.core.di
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import dagger.MapKey
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
@MapKey
|
||||||
|
annotation class FragmentKey(val value: KClass<out Fragment>)
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.riotx.core.di
|
||||||
|
|
||||||
|
import androidx.fragment.app.FragmentFactory
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import dagger.Binds
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.multibindings.IntoMap
|
||||||
|
import im.vector.riotx.core.platform.ConfigurationViewModel
|
||||||
|
import im.vector.riotx.features.crypto.keysbackup.restore.KeysBackupRestoreFromKeyViewModel
|
||||||
|
import im.vector.riotx.features.crypto.keysbackup.restore.KeysBackupRestoreFromPassphraseViewModel
|
||||||
|
import im.vector.riotx.features.crypto.keysbackup.restore.KeysBackupRestoreSharedViewModel
|
||||||
|
import im.vector.riotx.features.crypto.keysbackup.setup.KeysBackupSetupSharedViewModel
|
||||||
|
import im.vector.riotx.features.crypto.verification.SasVerificationViewModel
|
||||||
|
import im.vector.riotx.features.home.HomeNavigationViewModel
|
||||||
|
import im.vector.riotx.features.home.createdirect.CreateDirectRoomNavigationViewModel
|
||||||
|
import im.vector.riotx.features.home.room.list.RoomListFragment
|
||||||
|
import im.vector.riotx.features.reactions.EmojiChooserViewModel
|
||||||
|
import im.vector.riotx.features.roomdirectory.RoomDirectoryNavigationViewModel
|
||||||
|
import im.vector.riotx.features.workers.signout.SignOutViewModel
|
||||||
|
|
||||||
|
@Module
|
||||||
|
interface FragmentModule {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fragments with @IntoMap will be injected by this factory
|
||||||
|
*/
|
||||||
|
@Binds
|
||||||
|
fun bindFragmentFactory(factory: VectorFragmentFactory): FragmentFactory
|
||||||
|
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@FragmentKey(RoomListFragment::class)
|
||||||
|
fun bindRoomListFragment(viewModel: RoomListFragment): ViewModel
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -17,6 +17,7 @@
|
||||||
package im.vector.riotx.core.di
|
package im.vector.riotx.core.di
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.fragment.app.FragmentFactory
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import dagger.BindsInstance
|
import dagger.BindsInstance
|
||||||
import dagger.Component
|
import dagger.Component
|
||||||
|
@ -88,6 +89,8 @@ interface ScreenComponent {
|
||||||
|
|
||||||
fun activeSessionHolder(): ActiveSessionHolder
|
fun activeSessionHolder(): ActiveSessionHolder
|
||||||
|
|
||||||
|
fun fragmentFactory(): FragmentFactory
|
||||||
|
|
||||||
fun viewModelFactory(): ViewModelProvider.Factory
|
fun viewModelFactory(): ViewModelProvider.Factory
|
||||||
|
|
||||||
fun bugReporter(): BugReporter
|
fun bugReporter(): BugReporter
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.riotx.core.di
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentFactory
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import timber.log.Timber
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Provider
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FragmentFactory which uses Dagger to create the instances.
|
||||||
|
*/
|
||||||
|
class VectorFragmentFactory @Inject constructor(
|
||||||
|
private val creators: @JvmSuppressWildcards Map<Class<out Fragment>, Provider<Fragment>>
|
||||||
|
) : FragmentFactory() {
|
||||||
|
|
||||||
|
override fun instantiate(classLoader: ClassLoader, className: String): Fragment {
|
||||||
|
val fragmentClass = loadFragmentClass(classLoader, className)
|
||||||
|
val creator: Provider<out Fragment>? = creators[fragmentClass]
|
||||||
|
return if (creator == null) {
|
||||||
|
Timber.v("Unknown model class: $className, fallback to default instance")
|
||||||
|
super.instantiate(classLoader, className)
|
||||||
|
} else {
|
||||||
|
creator.get()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,15 +19,15 @@ package im.vector.riotx.core.extensions
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
|
||||||
fun Fragment.addFragment(fragment: Fragment, frameId: Int) {
|
fun Fragment.addFragment(fragment: Fragment, frameId: Int) {
|
||||||
fragmentManager?.inTransaction { add(frameId, fragment) }
|
parentFragmentManager.inTransaction { add(frameId, fragment) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Fragment.replaceFragment(fragment: Fragment, frameId: Int) {
|
fun Fragment.replaceFragment(fragment: Fragment, frameId: Int) {
|
||||||
fragmentManager?.inTransaction { replace(frameId, fragment) }
|
parentFragmentManager.inTransaction { replace(frameId, fragment) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Fragment.addFragmentToBackstack(fragment: Fragment, frameId: Int, tag: String? = null) {
|
fun Fragment.addFragmentToBackstack(fragment: Fragment, frameId: Int, tag: String? = null) {
|
||||||
fragmentManager?.inTransaction { replace(frameId, fragment).addToBackStack(tag) }
|
parentFragmentManager.inTransaction { replace(frameId, fragment).addToBackStack(tag) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Fragment.addChildFragment(fragment: Fragment, frameId: Int) {
|
fun Fragment.addChildFragment(fragment: Fragment, frameId: Int) {
|
||||||
|
|
|
@ -26,6 +26,7 @@ import androidx.annotation.*
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.fragment.app.FragmentFactory
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
@ -125,7 +126,7 @@ abstract class VectorBaseActivity : BaseMvRxActivity(), HasScreenInjector {
|
||||||
}
|
}
|
||||||
Timber.v("Injecting dependencies into ${javaClass.simpleName} took $timeForInjection ms")
|
Timber.v("Injecting dependencies into ${javaClass.simpleName} took $timeForInjection ms")
|
||||||
ThemeUtils.setActivityTheme(this, getOtherThemes())
|
ThemeUtils.setActivityTheme(this, getOtherThemes())
|
||||||
|
supportFragmentManager.fragmentFactory = screenComponent.fragmentFactory()
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
viewModelFactory = screenComponent.viewModelFactory()
|
viewModelFactory = screenComponent.viewModelFactory()
|
||||||
configurationViewModel = ViewModelProviders.of(this, viewModelFactory).get(ConfigurationViewModel::class.java)
|
configurationViewModel = ViewModelProviders.of(this, viewModelFactory).get(ConfigurationViewModel::class.java)
|
||||||
|
|
|
@ -134,7 +134,11 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), HasScreenInjector {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun setArguments(args: Parcelable? = null) {
|
protected fun setArguments(args: Parcelable? = null) {
|
||||||
arguments = args?.let { Bundle().apply { putParcelable(MvRx.KEY_ARG, it) } }
|
arguments = args.toMvRxBundle()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun Parcelable?.toMvRxBundle(): Bundle? {
|
||||||
|
return this?.let { Bundle().apply { putParcelable(MvRx.KEY_ARG, it) } }
|
||||||
}
|
}
|
||||||
|
|
||||||
@MainThread
|
@MainThread
|
||||||
|
|
|
@ -30,6 +30,7 @@ import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupState
|
||||||
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
import im.vector.riotx.core.di.ScreenComponent
|
import im.vector.riotx.core.di.ScreenComponent
|
||||||
|
import im.vector.riotx.core.extensions.inTransaction
|
||||||
import im.vector.riotx.core.platform.ToolbarConfigurable
|
import im.vector.riotx.core.platform.ToolbarConfigurable
|
||||||
import im.vector.riotx.core.platform.VectorBaseFragment
|
import im.vector.riotx.core.platform.VectorBaseFragment
|
||||||
import im.vector.riotx.core.ui.views.KeysBackupBanner
|
import im.vector.riotx.core.ui.views.KeysBackupBanner
|
||||||
|
@ -172,14 +173,17 @@ class HomeDetailFragment : VectorBaseFragment(), KeysBackupBanner.Delegate {
|
||||||
|
|
||||||
private fun updateSelectedFragment(displayMode: RoomListFragment.DisplayMode) {
|
private fun updateSelectedFragment(displayMode: RoomListFragment.DisplayMode) {
|
||||||
val fragmentTag = "FRAGMENT_TAG_${displayMode.name}"
|
val fragmentTag = "FRAGMENT_TAG_${displayMode.name}"
|
||||||
var fragment = childFragmentManager.findFragmentByTag(fragmentTag)
|
val fragment = childFragmentManager.findFragmentByTag(fragmentTag)
|
||||||
if (fragment == null) {
|
if (fragment == null) {
|
||||||
fragment = RoomListFragment.newInstance(RoomListParams(displayMode))
|
childFragmentManager.inTransaction {
|
||||||
|
replace(R.id.roomListContainer, RoomListFragment::class.java, RoomListParams(displayMode).toMvRxBundle(), fragmentTag).addToBackStack(fragmentTag)
|
||||||
}
|
}
|
||||||
childFragmentManager.beginTransaction()
|
} else {
|
||||||
.replace(R.id.roomListContainer, fragment, fragmentTag)
|
childFragmentManager.inTransaction {
|
||||||
.addToBackStack(fragmentTag)
|
replace(R.id.roomListContainer, fragment, fragmentTag).addToBackStack(fragmentTag)
|
||||||
.commit()
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ==========================================================================================
|
/* ==========================================================================================
|
||||||
|
|
|
@ -44,7 +44,6 @@ class FilteredRoomsActivity : VectorBaseActivity() {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
configureToolbar(filteredRoomsToolbar)
|
configureToolbar(filteredRoomsToolbar)
|
||||||
if (isFirstCreation()) {
|
if (isFirstCreation()) {
|
||||||
roomListFragment = RoomListFragment.newInstance(RoomListParams(RoomListFragment.DisplayMode.FILTERED))
|
|
||||||
replaceFragment(roomListFragment, R.id.filteredRoomsFragmentContainer, FRAGMENT_TAG)
|
replaceFragment(roomListFragment, R.id.filteredRoomsFragmentContainer, FRAGMENT_TAG)
|
||||||
} else {
|
} else {
|
||||||
roomListFragment = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG) as RoomListFragment
|
roomListFragment = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG) as RoomListFragment
|
||||||
|
|
|
@ -52,7 +52,13 @@ data class RoomListParams(
|
||||||
val sharedData: SharedData? = null
|
val sharedData: SharedData? = null
|
||||||
) : Parcelable
|
) : Parcelable
|
||||||
|
|
||||||
class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, OnBackPressed, FabMenuView.Listener {
|
class RoomListFragment @Inject constructor(
|
||||||
|
private val roomController: RoomSummaryController,
|
||||||
|
val roomListViewModelFactory: RoomListViewModel.Factory,
|
||||||
|
private val errorFormatter: ErrorFormatter,
|
||||||
|
private val notificationDrawerManager: NotificationDrawerManager
|
||||||
|
|
||||||
|
) : VectorBaseFragment(), RoomSummaryController.Listener, OnBackPressed, FabMenuView.Listener {
|
||||||
|
|
||||||
enum class DisplayMode(@StringRes val titleRes: Int) {
|
enum class DisplayMode(@StringRes val titleRes: Int) {
|
||||||
HOME(R.string.bottom_action_home),
|
HOME(R.string.bottom_action_home),
|
||||||
|
@ -62,25 +68,14 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O
|
||||||
SHARE(/* Not used */ 0)
|
SHARE(/* Not used */ 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun newInstance(roomListParams: RoomListParams): RoomListFragment {
|
|
||||||
return RoomListFragment().apply {
|
|
||||||
setArguments(roomListParams)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val roomListParams: RoomListParams by args()
|
private val roomListParams: RoomListParams by args()
|
||||||
@Inject lateinit var roomController: RoomSummaryController
|
|
||||||
@Inject lateinit var roomListViewModelFactory: RoomListViewModel.Factory
|
|
||||||
@Inject lateinit var errorFormatter: ErrorFormatter
|
|
||||||
@Inject lateinit var notificationDrawerManager: NotificationDrawerManager
|
|
||||||
private val roomListViewModel: RoomListViewModel by fragmentViewModel()
|
private val roomListViewModel: RoomListViewModel by fragmentViewModel()
|
||||||
|
|
||||||
override fun getLayoutResId() = R.layout.fragment_room_list
|
override fun getLayoutResId() = R.layout.fragment_room_list
|
||||||
|
|
||||||
override fun injectWith(injector: ScreenComponent) {
|
override fun injectWith(injector: ScreenComponent) {
|
||||||
injector.inject(this)
|
injector.inject(this)
|
||||||
|
setArguments()
|
||||||
}
|
}
|
||||||
|
|
||||||
private var hasUnreadRooms = false
|
private var hasUnreadRooms = false
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<FrameLayout
|
<androidx.fragment.app.FragmentContainerView
|
||||||
android:id="@+id/homeDetailFragmentContainer"
|
android:id="@+id/homeDetailFragmentContainer"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent" />
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
|
|
||||||
<FrameLayout
|
<androidx.fragment.app.FragmentContainerView
|
||||||
android:id="@+id/homeDrawerFragmentContainer"
|
android:id="@+id/homeDrawerFragmentContainer"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
|
Loading…
Reference in a new issue