Merge pull request #2481 from vector-im/feature/bma/upgrade

Upgrade of some library + cleanup
This commit is contained in:
Benoit Marty 2020-12-03 09:50:43 +01:00 committed by GitHub
commit a911492a9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 116 additions and 141 deletions

View File

@ -20,7 +20,8 @@ SDK API changes ⚠️:
-
Build 🧱:
-
- Upgrade some dependencies and Kotlin version
- Use fragment-ktx and preference-ktx dependencies (fix lint issue KtxExtensionAvailable)
Test:
-

View File

@ -66,7 +66,6 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation "androidx.fragment:fragment:1.3.0-beta01"
implementation "androidx.recyclerview:recyclerview:1.1.0"
implementation 'com.google.android.material:material:1.2.1'

View File

@ -2,8 +2,8 @@
buildscript {
// Ref: https://kotlinlang.org/releases.html
ext.kotlin_version = '1.4.10'
ext.kotlin_coroutines_version = "1.3.9"
ext.kotlin_version = '1.4.20'
ext.kotlin_coroutines_version = "1.4.1"
repositories {
google()
jcenter()
@ -12,7 +12,7 @@ buildscript {
}
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.0'
classpath 'com.android.tools.build:gradle:4.1.1'
classpath 'com.google.gms:google-services:4.3.4'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.7.1'

View File

@ -36,9 +36,9 @@ android {
dependencies {
implementation project(":matrix-sdk-android")
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation "androidx.fragment:fragment:1.3.0-beta01"
implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
// Paging
implementation "androidx.paging:paging-runtime-ktx:2.1.2"

View File

@ -21,34 +21,36 @@ import org.matrix.android.sdk.api.util.Cancelable
import io.reactivex.Completable
import io.reactivex.Single
fun <T> singleBuilder(builder: (callback: MatrixCallback<T>) -> Cancelable): Single<T> = Single.create {
val callback: MatrixCallback<T> = object : MatrixCallback<T> {
fun <T> singleBuilder(builder: (MatrixCallback<T>) -> Cancelable): Single<T> = Single.create { emitter ->
val callback = object : MatrixCallback<T> {
override fun onSuccess(data: T) {
it.onSuccess(data)
// Add `!!` to fix the warning:
// "Type mismatch: type parameter with nullable bounds is used T is used where T was expected. This warning will become an error soon"
emitter.onSuccess(data!!)
}
override fun onFailure(failure: Throwable) {
it.tryOnError(failure)
emitter.tryOnError(failure)
}
}
val cancelable = builder(callback)
it.setCancellable {
emitter.setCancellable {
cancelable.cancel()
}
}
fun <T> completableBuilder(builder: (callback: MatrixCallback<T>) -> Cancelable): Completable = Completable.create {
val callback: MatrixCallback<T> = object : MatrixCallback<T> {
fun <T> completableBuilder(builder: (MatrixCallback<T>) -> Cancelable): Completable = Completable.create { emitter ->
val callback = object : MatrixCallback<T> {
override fun onSuccess(data: T) {
it.onComplete()
emitter.onComplete()
}
override fun onFailure(failure: Throwable) {
it.tryOnError(failure)
emitter.tryOnError(failure)
}
}
val cancelable = builder(callback)
it.setCancellable {
emitter.setCancellable {
cancelable.cancel()
}
}

View File

@ -125,7 +125,6 @@ dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
implementation "androidx.appcompat:appcompat:1.2.0"
implementation "androidx.fragment:fragment:1.3.0-beta01"
implementation "androidx.core:core-ktx:1.3.2"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
@ -146,7 +145,7 @@ dependencies {
implementation "ru.noties.markwon:core:$markwon_version"
// Image
implementation 'androidx.exifinterface:exifinterface:1.3.0'
implementation 'androidx.exifinterface:exifinterface:1.3.1'
// Database
implementation 'com.github.Zhuinden:realm-monarchy:0.7.1'

View File

@ -31,6 +31,7 @@ import org.matrix.android.sdk.internal.extensions.toUnsignedInt
import org.matrix.olm.OlmSAS
import org.matrix.olm.OlmUtility
import timber.log.Timber
import java.util.Locale
/**
* Represents an ongoing short code interactive key verification between two devices.
@ -344,7 +345,7 @@ internal abstract class SASDefaultVerificationTransaction(
}
protected fun hashUsingAgreedHashMethod(toHash: String): String? {
if ("sha256".toLowerCase() == accepted?.hash?.toLowerCase()) {
if ("sha256" == accepted?.hash?.toLowerCase(Locale.ROOT)) {
val olmUtil = OlmUtility()
val hashBytes = olmUtil.sha256(toHash)
olmUtil.releaseUtility()
@ -354,12 +355,11 @@ internal abstract class SASDefaultVerificationTransaction(
}
private fun macUsingAgreedMethod(message: String, info: String): String? {
if (SAS_MAC_SHA256_LONGKDF.toLowerCase() == accepted?.messageAuthenticationCode?.toLowerCase()) {
return getSAS().calculateMacLongKdf(message, info)
} else if (SAS_MAC_SHA256.toLowerCase() == accepted?.messageAuthenticationCode?.toLowerCase()) {
return getSAS().calculateMac(message, info)
return when (accepted?.messageAuthenticationCode?.toLowerCase(Locale.ROOT)) {
SAS_MAC_SHA256_LONGKDF -> getSAS().calculateMacLongKdf(message, info)
SAS_MAC_SHA256 -> getSAS().calculateMac(message, info)
else -> null
}
return null
}
override fun getDecimalCodeRepresentation(): String {

View File

@ -17,6 +17,7 @@
package org.matrix.android.sdk.internal.util
import java.security.MessageDigest
import java.util.Locale
/**
* Compute a Hash of a String, using md5 algorithm
@ -26,7 +27,7 @@ fun String.md5() = try {
digest.update(toByteArray())
digest.digest()
.joinToString("") { String.format("%02X", it) }
.toLowerCase()
.toLowerCase(Locale.ROOT)
} catch (exc: Exception) {
// Should not happen, but just in case
hashCode().toString()

View File

@ -43,8 +43,8 @@ android {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation "androidx.fragment:fragment:1.3.0-beta01"
implementation 'androidx.exifinterface:exifinterface:1.3.0'
implementation "androidx.fragment:fragment-ktx:1.3.0-beta01"
implementation 'androidx.exifinterface:exifinterface:1.3.1'
// Log
implementation 'com.jakewharton.timber:timber:4.7.1'

View File

@ -315,9 +315,8 @@ dependencies {
implementation "androidx.recyclerview:recyclerview:1.2.0-alpha06"
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation "androidx.fragment:fragment:$fragment_version"
implementation "androidx.fragment:fragment-ktx:$fragment_version"
implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation "androidx.sharetarget:sharetarget:1.0.0"
implementation 'androidx.core:core-ktx:1.3.2'
@ -362,11 +361,11 @@ dependencies {
implementation "io.arrow-kt:arrow-core:$arrow_version"
// Pref
implementation 'androidx.preference:preference:1.1.1'
implementation 'androidx.preference:preference-ktx:1.1.1'
// UI
implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
implementation 'com.google.android.material:material:1.3.0-alpha02'
implementation 'com.google.android.material:material:1.3.0-alpha04'
implementation 'me.gujun.android:span:1.7'
implementation "io.noties.markwon:core:$markwon_version"
implementation "io.noties.markwon:html:$markwon_version"
@ -374,7 +373,7 @@ dependencies {
implementation 'me.saket:better-link-movement-method:2.2.0'
implementation 'com.google.android:flexbox:1.1.1'
implementation "androidx.autofill:autofill:$autofill_version"
implementation 'com.github.vector-im:PFLockScreen-Android:1.0.0-beta10'
implementation 'com.github.vector-im:PFLockScreen-Android:1.0.0-beta12'
// Custom Tab
implementation 'androidx.browser:browser:1.2.0'
@ -418,7 +417,7 @@ dependencies {
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.5.0'
// gplay flavor only
gplayImplementation('com.google.firebase:firebase-messaging:20.3.0') {
gplayImplementation('com.google.firebase:firebase-messaging:21.0.0') {
exclude group: 'com.google.firebase', module: 'firebase-core'
exclude group: 'com.google.firebase', module: 'firebase-analytics'
exclude group: 'com.google.firebase', module: 'firebase-measurement-connector'

View File

@ -41,6 +41,7 @@
<issue id="ObsoleteSdkInt" severity="error" />
<issue id="Recycle" severity="error" />
<issue id="KotlinPropertyAccess" severity="error" />
<issue id="DefaultLocale" severity="error" />
<issue id="InvalidPackage">
<!-- Ignore error from HtmlCompressor lib -->
@ -52,6 +53,9 @@
<!-- Manifest -->
<issue id="PermissionImpliesUnsupportedChromeOsHardware" severity="error" />
<!-- Dependencies -->
<issue id="KtxExtensionAvailable" severity="error" />
<!-- Timber -->
<!-- This rule is failing on CI because it's marked as unknwown rule id :/-->
<!-- <issue id="BinaryOperationInTimber" severity="error" />-->

View File

@ -18,7 +18,7 @@ package im.vector.app.gplay.features.settings.troubleshoot
import android.content.Intent
import androidx.activity.result.ActivityResultLauncher
import androidx.appcompat.app.AppCompatActivity
import com.google.firebase.iid.FirebaseInstanceId
import com.google.firebase.messaging.FirebaseMessaging
import im.vector.app.R
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.startAddGoogleAccountIntent
@ -36,29 +36,33 @@ class TestFirebaseToken @Inject constructor(private val context: AppCompatActivi
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
status = TestStatus.RUNNING
try {
FirebaseInstanceId.getInstance().instanceId
FirebaseMessaging.getInstance().token
.addOnCompleteListener(context) { task ->
if (!task.isSuccessful) {
val errorMsg = if (task.exception == null) "Unknown" else task.exception!!.localizedMessage
// Can't find where this constant is (not documented -or deprecated in docs- and all obfuscated)
if ("SERVICE_NOT_AVAILABLE".equals(errorMsg)) {
description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_service_not_available, errorMsg)
} else if ("TOO_MANY_REGISTRATIONS".equals(errorMsg)) {
description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_too_many_registration, errorMsg)
} else if ("ACCOUNT_MISSING".equals(errorMsg)) {
description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_account_missing, errorMsg)
description = when (val errorMsg = task.exception?.localizedMessage ?: "Unknown") {
"SERVICE_NOT_AVAILABLE" -> {
stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_service_not_available, errorMsg)
}
"TOO_MANY_REGISTRATIONS" -> {
stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_too_many_registration, errorMsg)
}
"ACCOUNT_MISSING" -> {
quickFix = object : TroubleshootQuickFix(R.string.settings_troubleshoot_test_fcm_failed_account_missing_quick_fix) {
override fun doFix() {
startAddGoogleAccountIntent(context, activityResultLauncher)
}
}
} else {
description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed, errorMsg)
stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed_account_missing, errorMsg)
}
else -> {
stringProvider.getString(R.string.settings_troubleshoot_test_fcm_failed, errorMsg)
}
}
status = TestStatus.FAILED
} else {
task.result?.token?.let { token ->
val tok = token.substring(0, Math.min(8, token.length)) + "********************"
task.result?.let { token ->
val tok = token.take(8) + "********************"
description = stringProvider.getString(R.string.settings_troubleshoot_test_fcm_success, tok)
Timber.e("Retrieved FCM token success [$tok].")
// Ensure it is well store in our local storage

View File

@ -21,7 +21,7 @@ import android.widget.Toast
import androidx.core.content.edit
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
import com.google.firebase.iid.FirebaseInstanceId
import com.google.firebase.messaging.FirebaseMessaging
import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.DefaultSharedPreferences
@ -71,14 +71,16 @@ object FcmHelper {
// 'app should always check the device for a compatible Google Play services APK before accessing Google Play services features'
if (checkPlayServices(activity)) {
try {
FirebaseInstanceId.getInstance().instanceId
.addOnSuccessListener(activity) { instanceIdResult ->
storeFcmToken(activity, instanceIdResult.token)
FirebaseMessaging.getInstance().token
.addOnSuccessListener { token ->
storeFcmToken(activity, token)
if (registerPusher) {
pushersManager.registerPusherWithFcmKey(instanceIdResult.token)
pushersManager.registerPusherWithFcmKey(token)
}
}
.addOnFailureListener(activity) { e -> Timber.e(e, "## ensureFcmTokenIsRetrieved() : failed") }
.addOnFailureListener { e ->
Timber.e(e, "## ensureFcmTokenIsRetrieved() : failed")
}
} catch (e: Throwable) {
Timber.e(e, "## ensureFcmTokenIsRetrieved() : failed")
}

View File

@ -21,6 +21,7 @@ import android.net.Uri
import android.webkit.MimeTypeMap
import im.vector.app.core.utils.getFileExtension
import timber.log.Timber
import java.util.Locale
/**
* Returns the mimetype from a uri.
@ -44,7 +45,7 @@ fun getMimeTypeFromUri(context: Context, uri: Uri): String? {
if (null != mimeType) {
// the mimetype is sometimes in uppercase.
mimeType = mimeType.toLowerCase()
mimeType = mimeType.toLowerCase(Locale.ROOT)
}
} catch (e: Exception) {
Timber.e(e, "Failed to open resource input stream")

View File

@ -43,7 +43,7 @@ abstract class VectorViewModel<S : MvRxState, VA : VectorViewModelAction, VE : V
* so you can use this in a switchMap or a flatMap
*/
// False positive
@Suppress("USELESS_CAST")
@Suppress("USELESS_CAST", "NULLABLE_TYPE_PARAMETER_AGAINST_NOT_NULL_TYPE_PARAMETER")
fun <T> Single<T>.toAsync(stateReducer: S.(Async<T>) -> S): Single<Async<T>> {
setState { stateReducer(Loading()) }
return map { Success(it) as Async<T> }
@ -56,7 +56,7 @@ abstract class VectorViewModel<S : MvRxState, VA : VectorViewModelAction, VE : V
* so you can use this in a switchMap or a flatMap
*/
// False positive
@Suppress("USELESS_CAST")
@Suppress("USELESS_CAST", "NULLABLE_TYPE_PARAMETER_AGAINST_NOT_NULL_TYPE_PARAMETER")
fun <T> Observable<T>.toAsync(stateReducer: S.(Async<T>) -> S): Observable<Async<T>> {
setState { stateReducer(Loading()) }
return map { Success(it) as Async<T> }

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2020 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.app.core.ui.bottomsheet
import com.airbnb.mvrx.MvRxState
import im.vector.app.core.platform.EmptyAction
import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel
abstract class BottomSheetGenericViewModel<State : MvRxState>(initialState: State) :
VectorViewModel<State, EmptyAction, EmptyViewEvents>(initialState) {
override fun handle(action: EmptyAction) {
// No op
}
}

View File

@ -44,7 +44,7 @@ open class BehaviorDataSource<T>(private val defaultValue: T? = null) : MutableD
}
override fun post(value: T) {
behaviorRelay.accept(value)
behaviorRelay.accept(value!!)
}
private fun createRelay(): BehaviorRelay<T> {
@ -68,6 +68,6 @@ open class PublishDataSource<T> : MutableDataSource<T> {
}
override fun post(value: T) {
publishRelay.accept(value)
publishRelay.accept(value!!)
}
}

View File

@ -19,6 +19,7 @@ package im.vector.app.core.utils
import android.content.Context
import timber.log.Timber
import java.io.File
import java.util.Locale
// Implementation should return true in case of success
typealias ActionOnFile = (file: File) -> Boolean
@ -113,7 +114,7 @@ fun getFileExtension(fileUri: String): String? {
val ext = filename.substring(dotPos + 1)
if (ext.isNotBlank()) {
return ext.toLowerCase()
return ext.toLowerCase(Locale.ROOT)
}
}
}

View File

@ -59,7 +59,6 @@ data class AttachmentsPreviewArgs(
) : Parcelable
class AttachmentsPreviewFragment @Inject constructor(
val viewModelFactory: AttachmentsPreviewViewModel.Factory,
private val attachmentMiniaturePreviewController: AttachmentMiniaturePreviewController,
private val attachmentBigPreviewController: AttachmentBigPreviewController,
private val colorProvider: ColorProvider

View File

@ -17,31 +17,12 @@
package im.vector.app.features.attachments.preview
import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.MvRxViewModelFactory
import com.airbnb.mvrx.ViewModelContext
import com.squareup.inject.assisted.Assisted
import com.squareup.inject.assisted.AssistedInject
import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorViewModel
class AttachmentsPreviewViewModel @AssistedInject constructor(@Assisted initialState: AttachmentsPreviewViewState)
class AttachmentsPreviewViewModel(initialState: AttachmentsPreviewViewState)
: VectorViewModel<AttachmentsPreviewViewState, AttachmentsPreviewAction, AttachmentsPreviewViewEvents>(initialState) {
@AssistedInject.Factory
interface Factory {
fun create(initialState: AttachmentsPreviewViewState): AttachmentsPreviewViewModel
}
companion object : MvRxViewModelFactory<AttachmentsPreviewViewModel, AttachmentsPreviewViewState> {
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: AttachmentsPreviewViewState): AttachmentsPreviewViewModel? {
val fragment: AttachmentsPreviewFragment = (viewModelContext as FragmentViewModelContext).fragment()
return fragment.viewModelFactory.create(state)
}
}
override fun handle(action: AttachmentsPreviewAction) {
when (action) {
is AttachmentsPreviewAction.SetCurrentAttachment -> handleSetCurrentAttachment(action)

View File

@ -74,6 +74,10 @@ class PinFragment @Inject constructor(
Toast.makeText(requireContext(), getString(R.string.create_pin_confirm_failure), Toast.LENGTH_SHORT).show()
}
override fun onPinCodeEnteredFirst(pinCode: String?): Boolean {
return false
}
override fun onCodeCreated(encodedCode: String) {
lifecycleScope.launch {
pinCodeStore.storeEncodedPin(encodedCode)

View File

@ -37,7 +37,6 @@ class RoomHistoryVisibilityBottomSheet : BottomSheetGeneric<RoomHistoryVisibilit
private lateinit var roomHistoryVisibilitySharedActionViewModel: RoomHistoryVisibilitySharedActionViewModel
@Inject lateinit var controller: RoomHistoryVisibilityController
@Inject lateinit var roomHistoryVisibilityViewModelFactory: RoomHistoryVisibilityViewModel.Factory
private val viewModel: RoomHistoryVisibilityViewModel by fragmentViewModel(RoomHistoryVisibilityViewModel::class)
override fun injectWith(injector: ScreenComponent) {

View File

@ -16,32 +16,7 @@
package im.vector.app.features.roomprofile.settings.historyvisibility
import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.MvRxViewModelFactory
import com.airbnb.mvrx.ViewModelContext
import com.squareup.inject.assisted.Assisted
import com.squareup.inject.assisted.AssistedInject
import im.vector.app.core.platform.EmptyAction
import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.ui.bottomsheet.BottomSheetGenericViewModel
class RoomHistoryVisibilityViewModel @AssistedInject constructor(@Assisted initialState: RoomHistoryVisibilityState)
: VectorViewModel<RoomHistoryVisibilityState, EmptyAction, EmptyViewEvents>(initialState) {
@AssistedInject.Factory
interface Factory {
fun create(initialState: RoomHistoryVisibilityState): RoomHistoryVisibilityViewModel
}
companion object : MvRxViewModelFactory<RoomHistoryVisibilityViewModel, RoomHistoryVisibilityState> {
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: RoomHistoryVisibilityState): RoomHistoryVisibilityViewModel? {
val fragment: RoomHistoryVisibilityBottomSheet = (viewModelContext as FragmentViewModelContext).fragment()
return fragment.roomHistoryVisibilityViewModelFactory.create(state)
}
}
override fun handle(action: EmptyAction) {
// No op
}
}
class RoomHistoryVisibilityViewModel(initialState: RoomHistoryVisibilityState)
: BottomSheetGenericViewModel<RoomHistoryVisibilityState>(initialState)

View File

@ -39,7 +39,6 @@ class RoomJoinRuleBottomSheet : BottomSheetGeneric<RoomJoinRuleState, RoomJoinRu
private lateinit var roomJoinRuleSharedActionViewModel: RoomJoinRuleSharedActionViewModel
@Inject lateinit var controller: RoomJoinRuleController
@Inject lateinit var roomJoinRuleViewModelFactory: RoomJoinRuleViewModel.Factory
private val viewModel: RoomJoinRuleViewModel by fragmentViewModel(RoomJoinRuleViewModel::class)
override fun injectWith(injector: ScreenComponent) {

View File

@ -16,32 +16,7 @@
package im.vector.app.features.roomprofile.settings.joinrule
import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.MvRxViewModelFactory
import com.airbnb.mvrx.ViewModelContext
import com.squareup.inject.assisted.Assisted
import com.squareup.inject.assisted.AssistedInject
import im.vector.app.core.platform.EmptyAction
import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.ui.bottomsheet.BottomSheetGenericViewModel
class RoomJoinRuleViewModel @AssistedInject constructor(@Assisted initialState: RoomJoinRuleState)
: VectorViewModel<RoomJoinRuleState, EmptyAction, EmptyViewEvents>(initialState) {
@AssistedInject.Factory
interface Factory {
fun create(initialState: RoomJoinRuleState): RoomJoinRuleViewModel
}
companion object : MvRxViewModelFactory<RoomJoinRuleViewModel, RoomJoinRuleState> {
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: RoomJoinRuleState): RoomJoinRuleViewModel? {
val fragment: RoomJoinRuleBottomSheet = (viewModelContext as FragmentViewModelContext).fragment()
return fragment.roomJoinRuleViewModelFactory.create(state)
}
}
override fun handle(action: EmptyAction) {
// No op
}
}
class RoomJoinRuleViewModel(initialState: RoomJoinRuleState)
: BottomSheetGenericViewModel<RoomJoinRuleState>(initialState)