forked from GitHub-Mirror/riotX-android
Groups : add UI to show groups
This commit is contained in:
parent
a3539153ef
commit
64759abc9e
@ -7,6 +7,7 @@ import android.view.ViewGroup
|
|||||||
import im.vector.riotredesign.R
|
import im.vector.riotredesign.R
|
||||||
import im.vector.riotredesign.core.extensions.replaceFragment
|
import im.vector.riotredesign.core.extensions.replaceFragment
|
||||||
import im.vector.riotredesign.core.platform.RiotFragment
|
import im.vector.riotredesign.core.platform.RiotFragment
|
||||||
|
import im.vector.riotredesign.features.home.group.GroupListFragment
|
||||||
import im.vector.riotredesign.features.home.room.list.RoomListFragment
|
import im.vector.riotredesign.features.home.room.list.RoomListFragment
|
||||||
|
|
||||||
class HomeDrawerFragment : RiotFragment() {
|
class HomeDrawerFragment : RiotFragment() {
|
||||||
@ -25,10 +26,11 @@ class HomeDrawerFragment : RiotFragment() {
|
|||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
super.onActivityCreated(savedInstanceState)
|
super.onActivityCreated(savedInstanceState)
|
||||||
if (savedInstanceState == null) {
|
if (savedInstanceState == null) {
|
||||||
|
val groupListFragment = GroupListFragment.newInstance()
|
||||||
|
replaceFragment(groupListFragment, R.id.groupListFragmentContainer)
|
||||||
val roomListFragment = RoomListFragment.newInstance()
|
val roomListFragment = RoomListFragment.newInstance()
|
||||||
replaceFragment(roomListFragment, R.id.roomListFragmentContainer)
|
replaceFragment(roomListFragment, R.id.roomListFragmentContainer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package im.vector.riotredesign.features.home.group
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||||
|
|
||||||
|
sealed class GroupListActions {
|
||||||
|
|
||||||
|
data class SelectGroup(val groupSummary: GroupSummary) : GroupListActions()
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
package im.vector.riotredesign.features.home.group
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import com.airbnb.mvrx.Incomplete
|
||||||
|
import com.airbnb.mvrx.Success
|
||||||
|
import com.airbnb.mvrx.fragmentViewModel
|
||||||
|
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||||
|
import im.vector.riotredesign.R
|
||||||
|
import im.vector.riotredesign.core.platform.RiotFragment
|
||||||
|
import im.vector.riotredesign.core.platform.StateView
|
||||||
|
import kotlinx.android.synthetic.main.fragment_room_list.*
|
||||||
|
|
||||||
|
class GroupListFragment : RiotFragment(), GroupSummaryController.Callback {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun newInstance(): GroupListFragment {
|
||||||
|
return GroupListFragment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val viewModel: GroupListViewModel by fragmentViewModel()
|
||||||
|
private lateinit var roomController: GroupSummaryController
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
|
return inflater.inflate(R.layout.fragment_group_list, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
roomController = GroupSummaryController(this)
|
||||||
|
stateView.contentView = epoxyRecyclerView
|
||||||
|
epoxyRecyclerView.setController(roomController)
|
||||||
|
viewModel.subscribe { renderState(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderState(state: GroupListViewState) {
|
||||||
|
when (state.async) {
|
||||||
|
is Incomplete -> renderLoading()
|
||||||
|
is Success -> renderSuccess(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderSuccess(state: GroupListViewState) {
|
||||||
|
stateView.state = StateView.State.Content
|
||||||
|
roomController.setData(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderLoading() {
|
||||||
|
stateView.state = StateView.State.Loading
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onGroupSelected(groupSummary: GroupSummary) {
|
||||||
|
viewModel.accept(GroupListActions.SelectGroup(groupSummary))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package im.vector.riotredesign.features.home.group
|
||||||
|
|
||||||
|
import android.support.v4.app.FragmentActivity
|
||||||
|
import com.airbnb.mvrx.BaseMvRxViewModel
|
||||||
|
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||||
|
import im.vector.matrix.android.api.Matrix
|
||||||
|
import im.vector.matrix.android.api.session.Session
|
||||||
|
import im.vector.matrix.rx.rx
|
||||||
|
import org.koin.android.ext.android.get
|
||||||
|
|
||||||
|
class GroupListViewModel(initialState: GroupListViewState,
|
||||||
|
private val session: Session
|
||||||
|
) : BaseMvRxViewModel<GroupListViewState>(initialState) {
|
||||||
|
|
||||||
|
companion object : MvRxViewModelFactory<GroupListViewState> {
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
override fun create(activity: FragmentActivity, state: GroupListViewState): GroupListViewModel {
|
||||||
|
val matrix = activity.get<Matrix>()
|
||||||
|
val currentSession = matrix.currentSession
|
||||||
|
return GroupListViewModel(state, currentSession)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
observeGroupSummaries()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun accept(action: GroupListActions) {
|
||||||
|
when (action) {
|
||||||
|
is GroupListActions.SelectGroup -> handleSelectGroup(action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PRIVATE METHODS *****************************************************************************
|
||||||
|
|
||||||
|
private fun handleSelectGroup(action: GroupListActions.SelectGroup) {
|
||||||
|
withState { state ->
|
||||||
|
if (state.selectedGroup?.groupId != action.groupSummary.groupId) {
|
||||||
|
setState { copy(selectedGroup = action.groupSummary) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun observeGroupSummaries() {
|
||||||
|
session
|
||||||
|
.rx().liveGroupSummaries()
|
||||||
|
.execute { async ->
|
||||||
|
copy(async = async)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package im.vector.riotredesign.features.home.group
|
||||||
|
|
||||||
|
import com.airbnb.mvrx.Async
|
||||||
|
import com.airbnb.mvrx.MvRxState
|
||||||
|
import com.airbnb.mvrx.Uninitialized
|
||||||
|
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||||
|
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||||
|
|
||||||
|
data class GroupListViewState(
|
||||||
|
val async: Async<List<GroupSummary>> = Uninitialized,
|
||||||
|
val selectedGroup: GroupSummary? = null
|
||||||
|
) : MvRxState
|
@ -0,0 +1,34 @@
|
|||||||
|
package im.vector.riotredesign.features.home.group
|
||||||
|
|
||||||
|
import com.airbnb.epoxy.TypedEpoxyController
|
||||||
|
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||||
|
|
||||||
|
class GroupSummaryController(private val callback: Callback? = null
|
||||||
|
) : TypedEpoxyController<GroupListViewState>() {
|
||||||
|
|
||||||
|
override fun buildModels(viewState: GroupListViewState) {
|
||||||
|
buildGroupModels(viewState.async(), viewState.selectedGroup)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildGroupModels(summaries: List<GroupSummary>?, selected: GroupSummary?) {
|
||||||
|
if (summaries.isNullOrEmpty()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
summaries.forEach { groupSummary ->
|
||||||
|
val isSelected = groupSummary.groupId == selected?.groupId
|
||||||
|
GroupSummaryItem(
|
||||||
|
groupName = groupSummary.displayName,
|
||||||
|
avatarUrl = groupSummary.avatarUrl,
|
||||||
|
isSelected = isSelected,
|
||||||
|
listener = { callback?.onGroupSelected(groupSummary) }
|
||||||
|
)
|
||||||
|
.id(groupSummary.groupId)
|
||||||
|
.addTo(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Callback {
|
||||||
|
fun onGroupSelected(groupSummary: GroupSummary)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package im.vector.riotredesign.features.home.group
|
||||||
|
|
||||||
|
import android.widget.ImageView
|
||||||
|
import im.vector.riotredesign.R
|
||||||
|
import im.vector.riotredesign.core.epoxy.KotlinModel
|
||||||
|
import im.vector.riotredesign.features.home.AvatarRenderer
|
||||||
|
|
||||||
|
|
||||||
|
data class GroupSummaryItem(
|
||||||
|
val groupName: CharSequence,
|
||||||
|
val avatarUrl: String?,
|
||||||
|
val isSelected: Boolean,
|
||||||
|
val listener: (() -> Unit)? = null
|
||||||
|
) : KotlinModel(R.layout.item_group) {
|
||||||
|
|
||||||
|
private val avatarImageView by bind<ImageView>(R.id.groupAvatarImageView)
|
||||||
|
|
||||||
|
override fun bind() {
|
||||||
|
AvatarRenderer.render(avatarUrl, groupName.toString(), avatarImageView)
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package im.vector.riotredesign.features.home.room.list
|
package im.vector.riotredesign.features.home.room.list
|
||||||
|
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||||
|
import im.vector.riotredesign.features.home.group.GroupListActions
|
||||||
|
|
||||||
sealed class RoomListActions {
|
sealed class RoomListActions {
|
||||||
|
|
||||||
|
@ -6,6 +6,9 @@ import com.airbnb.mvrx.MvRxViewModelFactory
|
|||||||
import im.vector.matrix.android.api.Matrix
|
import im.vector.matrix.android.api.Matrix
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
import im.vector.matrix.rx.rx
|
import im.vector.matrix.rx.rx
|
||||||
|
import im.vector.riotredesign.features.home.group.GroupListActions
|
||||||
|
import im.vector.riotredesign.features.home.group.GroupListViewModel
|
||||||
|
import im.vector.riotredesign.features.home.group.GroupListViewState
|
||||||
import org.koin.android.ext.android.get
|
import org.koin.android.ext.android.get
|
||||||
|
|
||||||
class RoomListViewModel(initialState: RoomListViewState,
|
class RoomListViewModel(initialState: RoomListViewState,
|
||||||
|
@ -2,6 +2,8 @@ package im.vector.riotredesign.features.home.room.list
|
|||||||
|
|
||||||
import com.airbnb.epoxy.TypedEpoxyController
|
import com.airbnb.epoxy.TypedEpoxyController
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||||
|
import im.vector.riotredesign.features.home.group.GroupListViewState
|
||||||
|
import im.vector.riotredesign.features.home.group.GroupSummaryItem
|
||||||
|
|
||||||
class RoomSummaryController(private val callback: Callback? = null
|
class RoomSummaryController(private val callback: Callback? = null
|
||||||
) : TypedEpoxyController<RoomListViewState>() {
|
) : TypedEpoxyController<RoomListViewState>() {
|
||||||
|
15
app/src/main/res/layout/fragment_group_list.xml
Normal file
15
app/src/main/res/layout/fragment_group_list.xml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
|
||||||
|
<im.vector.riotredesign.core.platform.StateView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/stateView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/dark">
|
||||||
|
|
||||||
|
<com.airbnb.epoxy.EpoxyRecyclerView
|
||||||
|
android:id="@+id/epoxyRecyclerView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
</im.vector.riotredesign.core.platform.StateView>
|
@ -6,10 +6,9 @@
|
|||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/communitiesFragmentContainer"
|
android:id="@+id/groupListFragmentContainer"
|
||||||
android:layout_width="56dp"
|
android:layout_width="56dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent" />
|
||||||
android:background="@color/dark" />
|
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/roomListFragmentContainer"
|
android:id="@+id/roomListFragmentContainer"
|
||||||
@ -17,7 +16,7 @@
|
|||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/communitiesFragmentContainer"
|
app:layout_constraintStart_toEndOf="@+id/groupListFragmentContainer"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
</android.support.constraint.ConstraintLayout>
|
</android.support.constraint.ConstraintLayout>
|
20
app/src/main/res/layout/item_group.xml
Normal file
20
app/src/main/res/layout/item_group.xml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<im.vector.riotredesign.core.platform.CheckableFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/itemGroupLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:padding="8dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/groupAvatarImageView"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
tools:src="@tools:sample/avatars" />
|
||||||
|
|
||||||
|
</im.vector.riotredesign.core.platform.CheckableFrameLayout>
|
Loading…
Reference in New Issue
Block a user