From 838003b68a4f04211fd758d0ea63380dc7cd3223 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 17 Jul 2019 18:30:14 +0200 Subject: [PATCH] Create direct room: start creating all the required stuff --- .../java/im/vector/matrix/rx/RxSession.kt | 5 ++ .../android/api/session/user/UserService.kt | 8 ++- .../session/user/DefaultUserService.kt | 14 +++- .../android/internal/util/StringUtils.kt | 8 +++ vector/src/main/AndroidManifest.xml | 1 + .../vector/riotx/core/di/ScreenComponent.kt | 3 + .../vector/riotx/core/di/ViewModelModule.kt | 5 ++ .../riotx/features/home/AvatarRenderer.kt | 8 +-- .../features/home/HomeDetailViewModel.kt | 20 +++--- .../riotx/features/home/HomeDrawerFragment.kt | 2 +- .../createdirect/CreateDirectRoomActivity.kt | 44 ++++++++++++ .../CreateDirectRoomController.kt | 70 +++++++++++++++++++ .../createdirect/CreateDirectRoomFragment.kt | 62 ++++++++++++++++ .../createdirect/CreateDirectRoomUserItem.kt | 56 +++++++++++++++ .../createdirect/CreateDirectRoomViewModel.kt | 59 ++++++++++++++++ .../createdirect/CreateDirectRoomViewState.kt | 28 ++++++++ .../home/room/list/RoomListFragment.kt | 4 +- .../features/navigation/DefaultNavigator.kt | 7 ++ .../riotx/features/navigation/Navigator.kt | 2 + .../layout/fragment_create_direct_room.xml | 14 ++++ .../layout/item_create_direct_room_user.xml | 43 ++++++++++++ 21 files changed, 442 insertions(+), 21 deletions(-) create mode 100644 vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomActivity.kt create mode 100644 vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomController.kt create mode 100644 vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomFragment.kt create mode 100644 vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomUserItem.kt create mode 100644 vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomViewModel.kt create mode 100644 vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomViewState.kt create mode 100644 vector/src/main/res/layout/fragment_create_direct_room.xml create mode 100644 vector/src/main/res/layout/item_create_direct_room_user.xml diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt index 30d31f942d..709b28e1e4 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt @@ -21,6 +21,7 @@ import im.vector.matrix.android.api.session.group.model.GroupSummary import im.vector.matrix.android.api.session.pushers.Pusher import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.sync.SyncState +import im.vector.matrix.android.api.session.user.model.User import io.reactivex.Observable import io.reactivex.schedulers.Schedulers @@ -42,6 +43,10 @@ class RxSession(private val session: Session) { return session.livePushers().asObservable().observeOn(Schedulers.computation()) } + fun liveUsers(): Observable> { + return session.liveUsers().asObservable().observeOn(Schedulers.computation()) + } + } fun Session.rx(): RxSession { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/user/UserService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/user/UserService.kt index eb09fbd20d..74dc444fd7 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/user/UserService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/user/UserService.kt @@ -36,6 +36,12 @@ interface UserService { * @param userId the userId to look for. * @return a Livedata of user with userId */ - fun observeUser(userId: String): LiveData + fun liveUser(userId: String): LiveData + + /** + * Observe a live list of users sorted alphabetically + * @return a Livedata of users + */ + fun liveUsers(): LiveData> } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/DefaultUserService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/DefaultUserService.kt index 477d5a7854..b0fded3b80 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/DefaultUserService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/user/DefaultUserService.kt @@ -24,6 +24,7 @@ import im.vector.matrix.android.api.session.user.model.User import im.vector.matrix.android.internal.database.RealmLiveData import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.model.UserEntity +import im.vector.matrix.android.internal.database.model.UserEntityFields import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.util.fetchCopied @@ -33,12 +34,12 @@ internal class DefaultUserService @Inject constructor(private val monarchy: Mona override fun getUser(userId: String): User? { val userEntity = monarchy.fetchCopied { UserEntity.where(it, userId).findFirst() } - ?: return null + ?: return null return userEntity.asDomain() } - override fun observeUser(userId: String): LiveData { + override fun liveUser(userId: String): LiveData { val liveRealmData = RealmLiveData(monarchy.realmConfiguration) { realm -> UserEntity.where(realm, userId) } @@ -48,4 +49,13 @@ internal class DefaultUserService @Inject constructor(private val monarchy: Mona .firstOrNull() } } + + override fun liveUsers(): LiveData> { + val liveRealmData = RealmLiveData(monarchy.realmConfiguration) { realm -> + realm.where(UserEntity::class.java).sort(UserEntityFields.DISPLAY_NAME) + } + return Transformations.map(liveRealmData) { results -> + results.map { it.asDomain() } + } + } } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/StringUtils.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/StringUtils.kt index a83ab0134c..a277498526 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/StringUtils.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/StringUtils.kt @@ -16,6 +16,7 @@ package im.vector.matrix.android.internal.util +import im.vector.matrix.android.api.MatrixPatterns import timber.log.Timber /** @@ -49,3 +50,10 @@ fun convertFromUTF8(s: String): String? { null } } + +fun String?.firstLetterOfDisplayName(): String { + if (this.isNullOrEmpty()) return "" + val isUserId = MatrixPatterns.isUserId(this) + val firstLetterIndex = if (isUserId) 1 else 0 + return this[firstLetterIndex].toString().toUpperCase() +} \ No newline at end of file diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index e0deced966..e4cdaee2e4 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -64,6 +64,7 @@ + diff --git a/vector/src/main/java/im/vector/riotx/core/di/ScreenComponent.kt b/vector/src/main/java/im/vector/riotx/core/di/ScreenComponent.kt index a42eec4940..0ff348b5a4 100644 --- a/vector/src/main/java/im/vector/riotx/core/di/ScreenComponent.kt +++ b/vector/src/main/java/im/vector/riotx/core/di/ScreenComponent.kt @@ -36,6 +36,7 @@ import im.vector.riotx.features.home.HomeActivity import im.vector.riotx.features.home.HomeDetailFragment import im.vector.riotx.features.home.HomeDrawerFragment import im.vector.riotx.features.home.HomeModule +import im.vector.riotx.features.home.createdirect.CreateDirectRoomFragment import im.vector.riotx.features.home.group.GroupListFragment import im.vector.riotx.features.home.room.detail.RoomDetailFragment import im.vector.riotx.features.home.room.detail.timeline.action.* @@ -153,6 +154,8 @@ interface ScreenComponent { fun inject(pushGatewaysFragment: PushGatewaysFragment) + fun inject(createDirectRoomFragment: CreateDirectRoomFragment) + @Component.Factory interface Factory { fun create(vectorComponent: VectorComponent, diff --git a/vector/src/main/java/im/vector/riotx/core/di/ViewModelModule.kt b/vector/src/main/java/im/vector/riotx/core/di/ViewModelModule.kt index 37abde20b8..c1daeb865c 100644 --- a/vector/src/main/java/im/vector/riotx/core/di/ViewModelModule.kt +++ b/vector/src/main/java/im/vector/riotx/core/di/ViewModelModule.kt @@ -30,6 +30,8 @@ import im.vector.riotx.features.crypto.keysbackup.settings.KeysBackupSettingsVie import im.vector.riotx.features.crypto.keysbackup.setup.KeysBackupSetupSharedViewModel import im.vector.riotx.features.crypto.verification.SasVerificationViewModel import im.vector.riotx.features.home.* +import im.vector.riotx.features.home.createdirect.CreateDirectRoomViewModel +import im.vector.riotx.features.home.createdirect.CreateDirectRoomViewModel_AssistedFactory import im.vector.riotx.features.home.group.GroupListViewModel import im.vector.riotx.features.home.group.GroupListViewModel_AssistedFactory import im.vector.riotx.features.home.room.detail.RoomDetailViewModel @@ -158,6 +160,9 @@ interface ViewModelModule { @Binds fun bindCreateRoomViewModelFactory(factory: CreateRoomViewModel_AssistedFactory): CreateRoomViewModel.Factory + @Binds + fun bindCreateDirectRoomViewModelFactory(factory: CreateDirectRoomViewModel_AssistedFactory): CreateDirectRoomViewModel.Factory + @Binds fun bindPushGatewaysViewModelFactory(factory: PushGatewaysViewModel_AssistedFactory): PushGatewaysViewModel.Factory diff --git a/vector/src/main/java/im/vector/riotx/features/home/AvatarRenderer.kt b/vector/src/main/java/im/vector/riotx/features/home/AvatarRenderer.kt index 83829e468c..2b6c1eb474 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/AvatarRenderer.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/AvatarRenderer.kt @@ -26,10 +26,10 @@ import com.amulyakhare.textdrawable.TextDrawable import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.target.DrawableImageViewTarget import com.bumptech.glide.request.target.Target -import im.vector.matrix.android.api.MatrixPatterns import im.vector.matrix.android.api.session.content.ContentUrlResolver import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.api.session.user.model.User +import im.vector.matrix.android.internal.util.firstLetterOfDisplayName import im.vector.riotx.R import im.vector.riotx.core.di.ActiveSessionHolder import im.vector.riotx.core.glide.GlideApp @@ -41,7 +41,7 @@ import javax.inject.Inject * This helper centralise ways to retrieve avatar into ImageView or even generic Target */ -class AvatarRenderer @Inject constructor(private val activeSessionHolder: ActiveSessionHolder){ +class AvatarRenderer @Inject constructor(private val activeSessionHolder: ActiveSessionHolder) { companion object { private const val THUMBNAIL_SIZE = 250 @@ -92,9 +92,7 @@ class AvatarRenderer @Inject constructor(private val activeSessionHolder: Active return if (text.isEmpty()) { TextDrawable.builder().buildRound("", avatarColor) } else { - val isUserId = MatrixPatterns.isUserId(text) - val firstLetterIndex = if (isUserId) 1 else 0 - val firstLetter = text[firstLetterIndex].toString().toUpperCase() + val firstLetter = text.firstLetterOfDisplayName() TextDrawable.builder() .beginConfig() .bold() diff --git a/vector/src/main/java/im/vector/riotx/features/home/HomeDetailViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/HomeDetailViewModel.kt index 7f0b610d65..917cafe149 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/HomeDetailViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/HomeDetailViewModel.kt @@ -73,21 +73,21 @@ class HomeDetailViewModel @AssistedInject constructor(@Assisted initialState: Ho .subscribe { list -> list.let { summaries -> val peopleNotifications = summaries - .filter { it.isDirect } - .map { it.notificationCount } - .takeIf { it.isNotEmpty() } - ?.sumBy { i -> i } - ?: 0 + .filter { it.isDirect } + .map { it.notificationCount } + .takeIf { it.isNotEmpty() } + ?.sumBy { i -> i } + ?: 0 val peopleHasHighlight = summaries .filter { it.isDirect } .any { it.highlightCount > 0 } val roomsNotifications = summaries - .filter { !it.isDirect } - .map { it.notificationCount } - .takeIf { it.isNotEmpty() } - ?.sumBy { i -> i } - ?: 0 + .filter { !it.isDirect } + .map { it.notificationCount } + .takeIf { it.isNotEmpty() } + ?.sumBy { i -> i } + ?: 0 val roomsHasHighlight = summaries .filter { !it.isDirect } .any { it.highlightCount > 0 } diff --git a/vector/src/main/java/im/vector/riotx/features/home/HomeDrawerFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/HomeDrawerFragment.kt index 832e8a5e4f..9159e32bc8 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/HomeDrawerFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/HomeDrawerFragment.kt @@ -52,7 +52,7 @@ class HomeDrawerFragment : VectorBaseFragment() { replaceChildFragment(groupListFragment, R.id.homeDrawerGroupListContainer) } - session.observeUser(session.sessionParams.credentials.userId).observeK(this) { user -> + session.liveUser(session.sessionParams.credentials.userId).observeK(this) { user -> if (user != null) { avatarRenderer.render(user.avatarUrl, user.userId, user.displayName, homeDrawerHeaderAvatarView) homeDrawerUsernameView.text = user.displayName diff --git a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomActivity.kt b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomActivity.kt new file mode 100644 index 0000000000..4ecb5f9f53 --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomActivity.kt @@ -0,0 +1,44 @@ +/* + * + * * 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.features.home.createdirect + +import android.content.Context +import android.content.Intent +import im.vector.riotx.R +import im.vector.riotx.core.extensions.addFragment +import im.vector.riotx.core.platform.VectorBaseActivity + +class CreateDirectRoomActivity : VectorBaseActivity() { + + override fun getLayoutRes() = R.layout.activity_simple + + override fun initUiAndData() { + if (isFirstCreation()) { + addFragment(CreateDirectRoomFragment(), R.id.simpleFragmentContainer) + } + } + + companion object { + fun getIntent(context: Context): Intent { + return Intent(context, CreateDirectRoomActivity::class.java) + } + } + + +} \ No newline at end of file diff --git a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomController.kt b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomController.kt new file mode 100644 index 0000000000..e435e726d1 --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomController.kt @@ -0,0 +1,70 @@ +/* + * + * * 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.features.home.createdirect + +import com.airbnb.epoxy.EpoxyController +import im.vector.matrix.android.api.session.user.model.User +import im.vector.matrix.android.internal.util.firstLetterOfDisplayName +import im.vector.riotx.features.home.AvatarRenderer +import javax.inject.Inject + +class CreateDirectRoomController @Inject constructor(private val avatarRenderer: AvatarRenderer) : EpoxyController() { + + private var state: CreateDirectRoomViewState? = null + var callback: Callback? = null + + init { + requestModelBuild() + } + + fun setData(state: CreateDirectRoomViewState) { + this.state = state + requestModelBuild() + } + + override fun buildModels() { + val currentState = state ?: return + val knownUsers = currentState.knownUsers() ?: return + + var lastFirstLetter: String? = null + knownUsers.forEach { user -> + val currentFirstLetter = user.displayName.firstLetterOfDisplayName() + val showLetter = lastFirstLetter != currentFirstLetter + lastFirstLetter = currentFirstLetter + createDirectRoomUserItem { + id(user.userId) + userId(user.userId) + showLetter(showLetter) + firstLetter(currentFirstLetter) + name(user.displayName) + avatarUrl(user.avatarUrl) + avatarRenderer(avatarRenderer) + clickListener { _ -> + callback?.onItemClick(user) + } + } + } + + } + + interface Callback { + fun onItemClick(user: User) + } + +} \ No newline at end of file diff --git a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomFragment.kt new file mode 100644 index 0000000000..f71998cbf2 --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomFragment.kt @@ -0,0 +1,62 @@ +/* + * + * * 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.features.home.createdirect + +import android.os.Bundle +import com.airbnb.mvrx.fragmentViewModel +import im.vector.matrix.android.api.session.user.model.User +import im.vector.riotx.R +import im.vector.riotx.core.di.ScreenComponent +import im.vector.riotx.core.platform.VectorBaseFragment +import kotlinx.android.synthetic.main.fragment_create_direct_room.* +import javax.inject.Inject + +class CreateDirectRoomFragment : VectorBaseFragment(), CreateDirectRoomController.Callback { + + override fun getLayoutResId() = R.layout.fragment_create_direct_room + + private val viewModel: CreateDirectRoomViewModel by fragmentViewModel() + + @Inject lateinit var createDirectRoomViewModelFactory: CreateDirectRoomViewModel.Factory + @Inject lateinit var directRoomController: CreateDirectRoomController + + override fun injectWith(injector: ScreenComponent) { + injector.inject(this) + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + setupRecyclerView() + viewModel.subscribe(this) { renderState(it) } + } + + private fun setupRecyclerView() { + recyclerView.setHasFixedSize(true) + directRoomController.callback = this + recyclerView.setController(directRoomController) + } + + private fun renderState(state: CreateDirectRoomViewState) { + directRoomController.setData(state) + } + + override fun onItemClick(user: User) { + vectorBaseActivity.notImplemented("IMPLEMENT ON USER CLICKED") + } +} \ No newline at end of file diff --git a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomUserItem.kt b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomUserItem.kt new file mode 100644 index 0000000000..c3b2d4f57e --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomUserItem.kt @@ -0,0 +1,56 @@ +/* + * + * * 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.features.home.createdirect + +import android.view.View +import android.widget.ImageView +import android.widget.TextView +import com.airbnb.epoxy.EpoxyAttribute +import com.airbnb.epoxy.EpoxyModelClass +import im.vector.riotx.R +import im.vector.riotx.core.epoxy.VectorEpoxyHolder +import im.vector.riotx.core.epoxy.VectorEpoxyModel +import im.vector.riotx.features.home.AvatarRenderer + +@EpoxyModelClass(layout = R.layout.item_create_direct_room_user) +abstract class CreateDirectRoomUserItem : VectorEpoxyModel() { + + @EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer + @EpoxyAttribute var showLetter: Boolean = false + @EpoxyAttribute var firstLetter: String = "" + @EpoxyAttribute var name: String? = null + @EpoxyAttribute var userId: String = "" + @EpoxyAttribute var avatarUrl: String? = null + @EpoxyAttribute var clickListener: View.OnClickListener? = null + + override fun bind(holder: Holder) { + holder.view.setOnClickListener(clickListener) + holder.nameView.text = name + holder.letterView.visibility = if (showLetter) View.VISIBLE else View.INVISIBLE + holder.letterView.text = firstLetter + avatarRenderer.render(avatarUrl, userId, name, holder.avatarImageView) + } + + class Holder : VectorEpoxyHolder() { + val letterView by bind(R.id.createDirectRoomUserLetter) + val nameView by bind(R.id.createDirectRoomUserName) + val avatarImageView by bind(R.id.createDirectRoomUserAvatar) + } + +} \ No newline at end of file diff --git a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomViewModel.kt new file mode 100644 index 0000000000..ce40bc0a22 --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomViewModel.kt @@ -0,0 +1,59 @@ +/* + * + * * 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.features.home.createdirect + +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.matrix.android.api.session.Session +import im.vector.matrix.rx.rx +import im.vector.riotx.core.platform.VectorViewModel + +class CreateDirectRoomViewModel @AssistedInject constructor(@Assisted + initialState: CreateDirectRoomViewState, + private val session: Session) + : VectorViewModel(initialState) { + + @AssistedInject.Factory + interface Factory { + fun create(initialState: CreateDirectRoomViewState): CreateDirectRoomViewModel + } + + companion object : MvRxViewModelFactory { + + @JvmStatic + override fun create(viewModelContext: ViewModelContext, state: CreateDirectRoomViewState): CreateDirectRoomViewModel? { + val fragment: CreateDirectRoomFragment = (viewModelContext as FragmentViewModelContext).fragment() + return fragment.createDirectRoomViewModelFactory.create(state) + } + } + + init { + observeKnownUsers() + } + + private fun observeKnownUsers() { + session.rx().liveUsers().execute { + this.copy(knownUsers = it) + } + } + +} \ No newline at end of file diff --git a/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomViewState.kt b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomViewState.kt new file mode 100644 index 0000000000..18b65357c1 --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/home/createdirect/CreateDirectRoomViewState.kt @@ -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.features.home.createdirect + +import com.airbnb.mvrx.Async +import com.airbnb.mvrx.MvRxState +import com.airbnb.mvrx.Uninitialized +import im.vector.matrix.android.api.session.user.model.User + +data class CreateDirectRoomViewState( + val knownUsers: Async> = Uninitialized +) : MvRxState \ No newline at end of file diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListFragment.kt index 491b0f4e68..935ae6897f 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/list/RoomListFragment.kt @@ -144,7 +144,7 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O } override fun createDirectChat() { - vectorBaseActivity.notImplemented("creating direct chat") + navigator.openCreateDirectRoom(requireActivity()) } private fun setupRecyclerView() { @@ -248,7 +248,7 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Listener, O return super.onBackPressed() } -// RoomSummaryController.Callback ************************************************************** + // RoomSummaryController.Callback ************************************************************** override fun onRoomSelected(room: RoomSummary) { roomListViewModel.accept(RoomListActions.SelectRoom(room)) diff --git a/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt index c9af93a369..8b8476e013 100644 --- a/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt @@ -25,6 +25,8 @@ import im.vector.riotx.core.utils.toast import im.vector.riotx.features.crypto.keysbackup.settings.KeysBackupManageActivity import im.vector.riotx.features.crypto.keysbackup.setup.KeysBackupSetupActivity import im.vector.riotx.features.debug.DebugMenuActivity +import im.vector.riotx.features.home.createdirect.CreateDirectRoomActivity +import im.vector.riotx.features.home.createdirect.CreateDirectRoomFragment import im.vector.riotx.features.home.room.detail.RoomDetailActivity import im.vector.riotx.features.home.room.detail.RoomDetailArgs import im.vector.riotx.features.home.room.filtered.FilteredRoomsActivity @@ -68,6 +70,11 @@ class DefaultNavigator @Inject constructor() : Navigator { context.startActivity(intent) } + override fun openCreateDirectRoom(context: Context) { + val intent = CreateDirectRoomActivity.getIntent(context) + context.startActivity(intent) + } + override fun openRoomsFiltering(context: Context) { val intent = FilteredRoomsActivity.newIntent(context) context.startActivity(intent) diff --git a/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt b/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt index 48f771184e..7c5a8c0af3 100644 --- a/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt +++ b/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt @@ -29,6 +29,8 @@ interface Navigator { fun openCreateRoom(context: Context) + fun openCreateDirectRoom(context: Context) + fun openRoomDirectory(context: Context) fun openRoomsFiltering(context: Context) diff --git a/vector/src/main/res/layout/fragment_create_direct_room.xml b/vector/src/main/res/layout/fragment_create_direct_room.xml new file mode 100644 index 0000000000..b683d0331e --- /dev/null +++ b/vector/src/main/res/layout/fragment_create_direct_room.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/vector/src/main/res/layout/item_create_direct_room_user.xml b/vector/src/main/res/layout/item_create_direct_room_user.xml new file mode 100644 index 0000000000..a078a5ee1c --- /dev/null +++ b/vector/src/main/res/layout/item_create_direct_room_user.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + \ No newline at end of file