mirror of
https://github.com/element-hq/element-android
synced 2024-11-24 10:25:35 +03:00
Create room screen - Better navigation pattern
This commit is contained in:
parent
4c5bffe0f5
commit
aa95ce3d02
8 changed files with 99 additions and 17 deletions
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.riotredesign.core.mvrx
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
import im.vector.riotredesign.core.platform.VectorViewModel
|
||||
import im.vector.riotredesign.core.utils.LiveEvent
|
||||
|
||||
// MvRx require a state with at least one attribute
|
||||
data class NavigationState(val dummy: Boolean = false) : MvRxState
|
||||
|
||||
abstract class NavigationViewModel<NavigationClass>(initialState: NavigationState) : VectorViewModel<NavigationState>(initialState) {
|
||||
|
||||
private val _navigateTo = MutableLiveData<LiveEvent<NavigationClass>>()
|
||||
val navigateTo: LiveData<LiveEvent<NavigationClass>>
|
||||
get() = _navigateTo
|
||||
|
||||
|
||||
fun goTo(navigation: NavigationClass) {
|
||||
_navigateTo.postValue(LiveEvent(navigation))
|
||||
}
|
||||
}
|
|
@ -40,6 +40,11 @@ abstract class FormEditTextItem : VectorEpoxyModel<FormEditTextItem.Holder>() {
|
|||
@EpoxyAttribute
|
||||
var onTextChange: ((String) -> Unit)? = null
|
||||
|
||||
private val onTextChangeListener = object : SimpleTextWatcher() {
|
||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||
onTextChange?.invoke(s.toString())
|
||||
}
|
||||
}
|
||||
|
||||
override fun bind(holder: Holder) {
|
||||
holder.textInputLayout.isEnabled = enabled
|
||||
|
@ -51,11 +56,7 @@ abstract class FormEditTextItem : VectorEpoxyModel<FormEditTextItem.Holder>() {
|
|||
}
|
||||
holder.textInputEditText.isEnabled = enabled
|
||||
|
||||
holder.textInputEditText.addTextChangedListener(object : SimpleTextWatcher() {
|
||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||
onTextChange?.invoke(s.toString())
|
||||
}
|
||||
})
|
||||
holder.textInputEditText.addTextChangedListener(onTextChangeListener)
|
||||
}
|
||||
|
||||
override fun shouldSaveViewState(): Boolean {
|
||||
|
@ -64,9 +65,7 @@ abstract class FormEditTextItem : VectorEpoxyModel<FormEditTextItem.Holder>() {
|
|||
|
||||
override fun unbind(holder: Holder) {
|
||||
super.unbind(holder)
|
||||
|
||||
// TODO Remove onTextChanged?
|
||||
|
||||
holder.textInputEditText.removeTextChangedListener(onTextChangeListener)
|
||||
}
|
||||
|
||||
class Holder : VectorEpoxyHolder() {
|
||||
|
|
|
@ -49,6 +49,7 @@ import java.util.concurrent.TimeUnit
|
|||
class PublicRoomsFragment : VectorBaseFragment(), PublicRoomsController.Callback {
|
||||
|
||||
private val viewModel: RoomDirectoryViewModel by activityViewModel()
|
||||
private val navigationViewModel: RoomDirectoryNavigationViewModel by activityViewModel()
|
||||
private val publicRoomsController: PublicRoomsController by inject()
|
||||
private val errorFormatter: ErrorFormatter by inject()
|
||||
|
||||
|
@ -76,8 +77,7 @@ class PublicRoomsFragment : VectorBaseFragment(), PublicRoomsController.Callback
|
|||
.disposeOnDestroy()
|
||||
|
||||
publicRoomsCreateNewRoom.setOnClickListener {
|
||||
// TODO Not the best navigation pattern
|
||||
(vectorBaseActivity as? RoomDirectoryActivity)?.gotoCreateRoom()
|
||||
navigationViewModel.goTo(RoomDirectoryActivity.Navigation.CreateRoom)
|
||||
}
|
||||
|
||||
viewModel.joinRoomErrorLiveData.observe(this, Observer {
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
package im.vector.riotredesign.features.roomdirectory
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.lifecycle.Observer
|
||||
import com.airbnb.mvrx.viewModel
|
||||
import im.vector.riotredesign.R
|
||||
import im.vector.riotredesign.core.extensions.addFragment
|
||||
import im.vector.riotredesign.core.extensions.addFragmentToBackstack
|
||||
|
@ -27,6 +29,14 @@ import org.koin.android.scope.ext.android.getOrCreateScope
|
|||
|
||||
class RoomDirectoryActivity : VectorBaseActivity() {
|
||||
|
||||
// Supported navigation actions for this Activity
|
||||
sealed class Navigation {
|
||||
object Back : Navigation()
|
||||
object CreateRoom : Navigation()
|
||||
}
|
||||
|
||||
|
||||
private val navigationViewModel: RoomDirectoryNavigationViewModel by viewModel()
|
||||
|
||||
override fun getLayoutRes() = R.layout.activity_simple
|
||||
|
||||
|
@ -34,6 +44,13 @@ class RoomDirectoryActivity : VectorBaseActivity() {
|
|||
super.onCreate(savedInstanceState)
|
||||
|
||||
bindScope(getOrCreateScope(RoomDirectoryModule.ROOM_DIRECTORY_SCOPE))
|
||||
|
||||
navigationViewModel.navigateTo.observe(this, Observer { liveEvent ->
|
||||
when (liveEvent.getContentIfNotHandled() ?: return@Observer) {
|
||||
is Navigation.Back -> onBackPressed()
|
||||
is Navigation.CreateRoom -> gotoCreateRoom()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun initUiAndData() {
|
||||
|
@ -42,8 +59,7 @@ class RoomDirectoryActivity : VectorBaseActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
fun gotoCreateRoom() {
|
||||
private fun gotoCreateRoom() {
|
||||
addFragmentToBackstack(CreateRoomFragment(), R.id.simpleFragmentContainer)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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.riotredesign.features.roomdirectory
|
||||
|
||||
import im.vector.riotredesign.core.mvrx.NavigationState
|
||||
import im.vector.riotredesign.core.mvrx.NavigationViewModel
|
||||
|
||||
class RoomDirectoryNavigationViewModel(initialState: NavigationState)
|
||||
: NavigationViewModel<RoomDirectoryActivity.Navigation>(initialState)
|
|
@ -20,11 +20,14 @@ import android.os.Bundle
|
|||
import android.view.MenuItem
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import im.vector.riotredesign.R
|
||||
import im.vector.riotredesign.core.platform.VectorBaseFragment
|
||||
import im.vector.riotredesign.features.roomdirectory.RoomDirectoryActivity
|
||||
import im.vector.riotredesign.features.roomdirectory.RoomDirectoryModule
|
||||
import im.vector.riotredesign.features.roomdirectory.RoomDirectoryNavigationViewModel
|
||||
import kotlinx.android.synthetic.main.fragment_create_room.*
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.android.scope.ext.android.bindScope
|
||||
|
@ -33,6 +36,7 @@ import timber.log.Timber
|
|||
|
||||
class CreateRoomFragment : VectorBaseFragment(), CreateRoomController.Listener {
|
||||
|
||||
private val navigationViewModel: RoomDirectoryNavigationViewModel by activityViewModel()
|
||||
private val viewModel: CreateRoomViewModel by fragmentViewModel()
|
||||
private val createRoomController: CreateRoomController by inject()
|
||||
|
||||
|
@ -49,8 +53,7 @@ class CreateRoomFragment : VectorBaseFragment(), CreateRoomController.Listener {
|
|||
setupRecyclerView()
|
||||
|
||||
createRoomClose.setOnClickListener {
|
||||
// TODO Not the best way to manage Fragment Backstack...
|
||||
vectorBaseActivity.onBackPressed()
|
||||
navigationViewModel.goTo(RoomDirectoryActivity.Navigation.Back)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ class CreateRoomViewModel(initialState: CreateRoomViewState,
|
|||
|
||||
fun setName(newName: String) = setState { copy(roomName = newName) }
|
||||
|
||||
fun setIsPublic(value: Boolean) = setState { copy(isPublic = value) }
|
||||
fun setIsPublic(isPublic: Boolean) = setState { copy(isPublic = isPublic) }
|
||||
|
||||
fun setIsInRoomDirectory(isInRoomDirectory: Boolean) = setState { copy(isInRoomDirectory = isInRoomDirectory) }
|
||||
|
||||
|
@ -59,6 +59,7 @@ class CreateRoomViewModel(initialState: CreateRoomViewState,
|
|||
// Directory visibility
|
||||
visibility = if (state.isInRoomDirectory) RoomDirectoryVisibility.PUBLIC else RoomDirectoryVisibility.PRIVATE
|
||||
|
||||
// Public room
|
||||
preset = if (state.isPublic) CreateRoomPreset.PRESET_PUBLIC_CHAT else CreateRoomPreset.PRESET_PRIVATE_CHAT
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,9 @@ import com.airbnb.mvrx.withState
|
|||
import im.vector.matrix.android.api.session.room.model.thirdparty.RoomDirectoryData
|
||||
import im.vector.riotredesign.R
|
||||
import im.vector.riotredesign.core.platform.VectorBaseFragment
|
||||
import im.vector.riotredesign.features.roomdirectory.RoomDirectoryActivity
|
||||
import im.vector.riotredesign.features.roomdirectory.RoomDirectoryModule
|
||||
import im.vector.riotredesign.features.roomdirectory.RoomDirectoryNavigationViewModel
|
||||
import im.vector.riotredesign.features.roomdirectory.RoomDirectoryViewModel
|
||||
import kotlinx.android.synthetic.main.fragment_room_directory_picker.*
|
||||
import org.koin.android.ext.android.inject
|
||||
|
@ -39,6 +41,7 @@ import timber.log.Timber
|
|||
class RoomDirectoryPickerFragment : VectorBaseFragment(), RoomDirectoryPickerController.Callback {
|
||||
|
||||
private val viewModel: RoomDirectoryViewModel by activityViewModel()
|
||||
private val navigationViewModel: RoomDirectoryNavigationViewModel by activityViewModel()
|
||||
private val pickerViewModel: RoomDirectoryPickerViewModel by fragmentViewModel()
|
||||
private val roomDirectoryPickerController: RoomDirectoryPickerController by inject()
|
||||
|
||||
|
@ -88,8 +91,7 @@ class RoomDirectoryPickerFragment : VectorBaseFragment(), RoomDirectoryPickerCon
|
|||
Timber.v("onRoomDirectoryClicked: $roomDirectoryData")
|
||||
viewModel.setRoomDirectoryData(roomDirectoryData)
|
||||
|
||||
// TODO Not the best way to manage Fragment Backstack...
|
||||
vectorBaseActivity.onBackPressed()
|
||||
navigationViewModel.goTo(RoomDirectoryActivity.Navigation.Back)
|
||||
}
|
||||
|
||||
override fun retry() {
|
||||
|
|
Loading…
Reference in a new issue