Home: start reworking UX [WIP]
This commit is contained in:
parent
0feb10315b
commit
268730e71b
|
@ -44,6 +44,7 @@
|
|||
android:label="@string/title_activity_emoji_reaction_picker" />
|
||||
|
||||
<activity android:name=".features.roomdirectory.RoomDirectoryActivity" />
|
||||
<activity android:name=".features.home.room.detail.RoomDetailActivity" />
|
||||
|
||||
<service
|
||||
android:name=".core.services.CallService"
|
||||
|
|
|
@ -21,7 +21,6 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import androidx.appcompat.app.ActionBarDrawerToggle
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.view.GravityCompat
|
||||
|
@ -32,12 +31,10 @@ import com.airbnb.mvrx.viewModel
|
|||
import im.vector.matrix.android.api.Matrix
|
||||
import im.vector.riotredesign.R
|
||||
import im.vector.riotredesign.core.extensions.hideKeyboard
|
||||
import im.vector.riotredesign.core.extensions.observeEvent
|
||||
import im.vector.riotredesign.core.extensions.replaceFragment
|
||||
import im.vector.riotredesign.core.platform.OnBackPressed
|
||||
import im.vector.riotredesign.core.platform.ToolbarConfigurable
|
||||
import im.vector.riotredesign.core.platform.VectorBaseActivity
|
||||
import im.vector.riotredesign.features.home.room.detail.LoadingRoomDetailFragment
|
||||
import im.vector.riotredesign.features.rageshake.BugReporter
|
||||
import im.vector.riotredesign.features.rageshake.VectorUncaughtExceptionHandler
|
||||
import im.vector.riotredesign.features.roomdirectory.RoomDirectoryActivity
|
||||
|
@ -71,13 +68,11 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||
drawerLayout.addDrawerListener(drawerListener)
|
||||
if (savedInstanceState == null) {
|
||||
val homeDrawerFragment = HomeDrawerFragment.newInstance()
|
||||
val loadingDetail = LoadingRoomDetailFragment.newInstance()
|
||||
val loadingDetail = LoadingFragment.newInstance()
|
||||
replaceFragment(loadingDetail, R.id.homeDetailFragmentContainer)
|
||||
replaceFragment(homeDrawerFragment, R.id.homeDrawerFragmentContainer)
|
||||
}
|
||||
homeActivityViewModel.openRoomLiveData.observeEvent(this) {
|
||||
homeNavigator.openRoomDetail(it, null)
|
||||
}
|
||||
|
||||
homeActivityViewModel.isLoading.observe(this, Observer<Boolean> {
|
||||
// TODO better UI
|
||||
if (it) {
|
||||
|
@ -115,30 +110,27 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||
override fun configure(toolbar: Toolbar) {
|
||||
setSupportActionBar(toolbar)
|
||||
supportActionBar?.setHomeButtonEnabled(true)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
val drawerToggle = ActionBarDrawerToggle(this, drawerLayout, toolbar, 0, 0)
|
||||
drawerLayout.addDrawerListener(drawerToggle)
|
||||
drawerToggle.syncState()
|
||||
supportActionBar?.setDisplayUseLogoEnabled(true)
|
||||
}
|
||||
|
||||
override fun getMenuRes() = R.menu.home
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
android.R.id.home -> {
|
||||
android.R.id.home -> {
|
||||
drawerLayout.openDrawer(GravityCompat.START)
|
||||
return true
|
||||
}
|
||||
R.id.sliding_menu_settings -> {
|
||||
R.id.sliding_menu_settings -> {
|
||||
startActivity(VectorSettingsActivity.getIntent(this, "TODO"))
|
||||
return true
|
||||
}
|
||||
R.id.sliding_menu_sign_out -> {
|
||||
R.id.sliding_menu_sign_out -> {
|
||||
SignOutUiWorker(this).perform(Matrix.getInstance().currentSession!!)
|
||||
return true
|
||||
}
|
||||
// TODO Temporary code here to create a room
|
||||
R.id.tmp_menu_create_room -> {
|
||||
R.id.tmp_menu_create_room -> {
|
||||
// Start Activity for now
|
||||
startActivity(Intent(this, RoomDirectoryActivity::class.java))
|
||||
return true
|
||||
|
|
|
@ -17,11 +17,12 @@
|
|||
package im.vector.riotredesign.features.home
|
||||
|
||||
import android.os.Bundle
|
||||
import im.vector.matrix.android.api.Matrix
|
||||
import im.vector.riotredesign.R
|
||||
import im.vector.riotredesign.core.extensions.replaceChildFragment
|
||||
import im.vector.riotredesign.core.platform.VectorBaseFragment
|
||||
import im.vector.riotredesign.features.home.group.GroupListFragment
|
||||
import im.vector.riotredesign.features.home.room.list.RoomListFragment
|
||||
import kotlinx.android.synthetic.main.fragment_home_drawer.*
|
||||
|
||||
class HomeDrawerFragment : VectorBaseFragment() {
|
||||
|
||||
|
@ -38,9 +39,14 @@ class HomeDrawerFragment : VectorBaseFragment() {
|
|||
super.onActivityCreated(savedInstanceState)
|
||||
if (savedInstanceState == null) {
|
||||
val groupListFragment = GroupListFragment.newInstance()
|
||||
replaceChildFragment(groupListFragment, R.id.groupListFragmentContainer)
|
||||
val roomListFragment = RoomListFragment.newInstance()
|
||||
replaceChildFragment(roomListFragment, R.id.roomListFragmentContainer)
|
||||
replaceChildFragment(groupListFragment, R.id.homeDrawerGroupListContainer)
|
||||
}
|
||||
val session = Matrix.getInstance().currentSession ?: return
|
||||
val user = session.getUser(session.sessionParams.credentials.userId)
|
||||
if (user != null) {
|
||||
AvatarRenderer.render(user.avatarUrl, user.userId, user.displayName, homeDrawerHeaderAvatarView)
|
||||
homeDrawerUsernameView.text = user.displayName
|
||||
homeDrawerUserIdView.text = user.userId
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,11 +18,13 @@ package im.vector.riotredesign.features.home
|
|||
|
||||
import androidx.core.view.GravityCompat
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||
import im.vector.riotredesign.R
|
||||
import im.vector.riotredesign.core.extensions.addFragmentToBackstack
|
||||
import im.vector.riotredesign.core.extensions.replaceFragment
|
||||
import im.vector.riotredesign.features.home.group.SelectedGroupFragment
|
||||
import im.vector.riotredesign.features.home.group.SelectedGroupParams
|
||||
import im.vector.riotredesign.features.home.room.detail.RoomDetailActivity
|
||||
import im.vector.riotredesign.features.home.room.detail.RoomDetailArgs
|
||||
import im.vector.riotredesign.features.home.room.detail.RoomDetailFragment
|
||||
import kotlinx.android.synthetic.main.activity_home.*
|
||||
import timber.log.Timber
|
||||
|
||||
|
@ -32,22 +34,25 @@ class HomeNavigator {
|
|||
|
||||
private var rootRoomId: String? = null
|
||||
|
||||
fun openSelectedGroup(groupSummary: GroupSummary) {
|
||||
Timber.v("Open selected group ${groupSummary.groupId}")
|
||||
activity?.let {
|
||||
val args = SelectedGroupParams(groupSummary.groupId, groupSummary.displayName, groupSummary.avatarUrl)
|
||||
val selectedGroupFragment = SelectedGroupFragment.newInstance(args)
|
||||
it.drawerLayout?.closeDrawer(GravityCompat.START)
|
||||
it.replaceFragment(selectedGroupFragment, R.id.homeDetailFragmentContainer)
|
||||
}
|
||||
}
|
||||
|
||||
fun openRoomDetail(roomId: String,
|
||||
eventId: String?,
|
||||
addToBackstack: Boolean = false) {
|
||||
Timber.v("Open room detail $roomId - $eventId - $addToBackstack")
|
||||
eventId: String?) {
|
||||
Timber.v("Open room detail $roomId - $eventId")
|
||||
activity?.let {
|
||||
//TODO enable eventId permalink. It doesn't work enough at the moment.
|
||||
val args = RoomDetailArgs(roomId)
|
||||
val roomDetailFragment = RoomDetailFragment.newInstance(args)
|
||||
it.drawerLayout?.closeDrawer(GravityCompat.START)
|
||||
if (addToBackstack) {
|
||||
it.addFragmentToBackstack(roomDetailFragment, R.id.homeDetailFragmentContainer, roomId)
|
||||
} else {
|
||||
rootRoomId = roomId
|
||||
clearBackStack(it.supportFragmentManager)
|
||||
it.replaceFragment(roomDetailFragment, R.id.homeDetailFragmentContainer)
|
||||
}
|
||||
val args = RoomDetailArgs(roomId)
|
||||
val roomDetailIntent = RoomDetailActivity.newIntent(it, args)
|
||||
it.startActivity(roomDetailIntent)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,10 +34,10 @@ class HomePermalinkHandler(private val navigator: HomeNavigator) {
|
|||
val permalinkData = PermalinkParser.parse(deepLink)
|
||||
when (permalinkData) {
|
||||
is PermalinkData.EventLink -> {
|
||||
navigator.openRoomDetail(permalinkData.roomIdOrAlias, permalinkData.eventId, true)
|
||||
navigator.openRoomDetail(permalinkData.roomIdOrAlias, permalinkData.eventId)
|
||||
}
|
||||
is PermalinkData.RoomLink -> {
|
||||
navigator.openRoomDetail(permalinkData.roomIdOrAlias, null, true)
|
||||
navigator.openRoomDetail(permalinkData.roomIdOrAlias, null)
|
||||
}
|
||||
is PermalinkData.GroupLink -> {
|
||||
navigator.openGroupDetail(permalinkData.groupId)
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
*
|
||||
* * 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.home
|
||||
|
||||
import android.graphics.drawable.AnimationDrawable
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import im.vector.riotredesign.R
|
||||
import im.vector.riotredesign.core.platform.VectorBaseFragment
|
||||
import kotlinx.android.synthetic.main.fragment_loading.*
|
||||
|
||||
class LoadingFragment : VectorBaseFragment() {
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance(): LoadingFragment {
|
||||
return LoadingFragment()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLayoutResId() = R.layout.fragment_loading
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val background = animatedLogoImageView.background
|
||||
if (background is AnimationDrawable) {
|
||||
background.start()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -22,9 +22,11 @@ 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.extensions.observeEvent
|
||||
import im.vector.riotredesign.core.platform.StateView
|
||||
import im.vector.riotredesign.core.platform.VectorBaseFragment
|
||||
import im.vector.riotredesign.features.home.HomeModule
|
||||
import im.vector.riotredesign.features.home.HomeNavigator
|
||||
import kotlinx.android.synthetic.main.fragment_group_list.*
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.android.scope.ext.android.bindScope
|
||||
|
@ -39,6 +41,7 @@ class GroupListFragment : VectorBaseFragment(), GroupSummaryController.Callback
|
|||
}
|
||||
|
||||
private val viewModel: GroupListViewModel by fragmentViewModel()
|
||||
private val homeNavigator by inject<HomeNavigator>()
|
||||
private val groupController by inject<GroupSummaryController>()
|
||||
|
||||
override fun getLayoutResId() = R.layout.fragment_group_list
|
||||
|
@ -50,6 +53,9 @@ class GroupListFragment : VectorBaseFragment(), GroupSummaryController.Callback
|
|||
stateView.contentView = epoxyRecyclerView
|
||||
epoxyRecyclerView.setController(groupController)
|
||||
viewModel.subscribe { renderState(it) }
|
||||
viewModel.openGroupLiveData.observeEvent(this) {
|
||||
homeNavigator.openSelectedGroup(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderState(state: GroupListViewState) {
|
||||
|
|
|
@ -16,17 +16,25 @@
|
|||
|
||||
package im.vector.riotredesign.features.home.group
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import arrow.core.Option
|
||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||
import com.airbnb.mvrx.ViewModelContext
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||
import im.vector.matrix.rx.rx
|
||||
import im.vector.riotredesign.core.platform.VectorViewModel
|
||||
import im.vector.riotredesign.core.resources.StringProvider
|
||||
import im.vector.riotredesign.core.utils.LiveEvent
|
||||
import org.koin.android.ext.android.get
|
||||
|
||||
const val ALL_COMMUNITIES_GROUP_ID = "ALL_COMMUNITIES_GROUP_ID"
|
||||
|
||||
class GroupListViewModel(initialState: GroupListViewState,
|
||||
private val selectedGroupHolder: SelectedGroupStore,
|
||||
private val session: Session
|
||||
private val session: Session,
|
||||
private val stringProvider: StringProvider
|
||||
) : VectorViewModel<GroupListViewState>(initialState) {
|
||||
|
||||
companion object : MvRxViewModelFactory<GroupListViewModel, GroupListViewState> {
|
||||
|
@ -35,10 +43,15 @@ class GroupListViewModel(initialState: GroupListViewState,
|
|||
override fun create(viewModelContext: ViewModelContext, state: GroupListViewState): GroupListViewModel? {
|
||||
val currentSession = viewModelContext.activity.get<Session>()
|
||||
val selectedGroupHolder = viewModelContext.activity.get<SelectedGroupStore>()
|
||||
return GroupListViewModel(state, selectedGroupHolder, currentSession)
|
||||
val stringProvider = viewModelContext.activity.get<StringProvider>()
|
||||
return GroupListViewModel(state, selectedGroupHolder, currentSession, stringProvider)
|
||||
}
|
||||
}
|
||||
|
||||
private val _openGroupLiveData = MutableLiveData<LiveEvent<GroupSummary>>()
|
||||
val openGroupLiveData: LiveData<LiveEvent<GroupSummary>>
|
||||
get() = _openGroupLiveData
|
||||
|
||||
init {
|
||||
observeGroupSummaries()
|
||||
observeState()
|
||||
|
@ -46,8 +59,8 @@ class GroupListViewModel(initialState: GroupListViewState,
|
|||
|
||||
private fun observeState() {
|
||||
subscribe {
|
||||
val selectedGroup = Option.fromNullable(it.selectedGroup)
|
||||
selectedGroupHolder.post(selectedGroup)
|
||||
val optionGroup = Option.fromNullable(it.selectedGroup)
|
||||
selectedGroupHolder.post(optionGroup)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,15 +75,21 @@ class GroupListViewModel(initialState: GroupListViewState,
|
|||
private fun handleSelectGroup(action: GroupListActions.SelectGroup) = withState { state ->
|
||||
if (state.selectedGroup?.groupId != action.groupSummary.groupId) {
|
||||
setState { copy(selectedGroup = action.groupSummary) }
|
||||
} else {
|
||||
setState { copy(selectedGroup = null) }
|
||||
_openGroupLiveData.postValue(LiveEvent(action.groupSummary))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun observeGroupSummaries() {
|
||||
session
|
||||
.rx().liveGroupSummaries()
|
||||
.map {
|
||||
val myUser = session.getUser(session.sessionParams.credentials.userId)
|
||||
val allCommunityGroup = GroupSummary(
|
||||
groupId = ALL_COMMUNITIES_GROUP_ID,
|
||||
displayName = "All Communities",
|
||||
avatarUrl = myUser?.avatarUrl ?: "")
|
||||
listOf(allCommunityGroup) + it
|
||||
}
|
||||
.execute { async ->
|
||||
copy(asyncGroups = async)
|
||||
}
|
||||
|
|
|
@ -16,13 +16,14 @@
|
|||
|
||||
package im.vector.riotredesign.features.home.group
|
||||
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
import com.airbnb.epoxy.EpoxyModelClass
|
||||
import im.vector.riotredesign.R
|
||||
import im.vector.riotredesign.core.epoxy.VectorEpoxyHolder
|
||||
import im.vector.riotredesign.core.epoxy.VectorEpoxyModel
|
||||
import im.vector.riotredesign.core.platform.CheckableFrameLayout
|
||||
import im.vector.riotredesign.features.home.AvatarRenderer
|
||||
|
||||
@EpoxyModelClass(layout = R.layout.item_group)
|
||||
|
@ -36,14 +37,15 @@ abstract class GroupSummaryItem : VectorEpoxyModel<GroupSummaryItem.Holder>() {
|
|||
|
||||
override fun bind(holder: Holder) {
|
||||
super.bind(holder)
|
||||
holder.rootView.isSelected = selected
|
||||
holder.rootView.setOnClickListener { listener?.invoke() }
|
||||
holder.groupNameView.text = groupName
|
||||
AvatarRenderer.render(avatarUrl, groupId, groupName.toString(), holder.avatarImageView)
|
||||
}
|
||||
|
||||
class Holder : VectorEpoxyHolder() {
|
||||
val avatarImageView by bind<ImageView>(R.id.groupAvatarImageView)
|
||||
val rootView by bind<CheckableFrameLayout>(R.id.itemGroupLayout)
|
||||
val groupNameView by bind<TextView>(R.id.groupNameView)
|
||||
val rootView by bind<ViewGroup>(R.id.itemGroupLayout)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
*
|
||||
* * 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.home.group
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import com.airbnb.mvrx.args
|
||||
import com.bumptech.glide.request.target.SimpleTarget
|
||||
import com.bumptech.glide.request.transition.Transition
|
||||
import im.vector.riotredesign.R
|
||||
import im.vector.riotredesign.core.extensions.replaceChildFragment
|
||||
import im.vector.riotredesign.core.glide.GlideApp
|
||||
import im.vector.riotredesign.core.platform.ToolbarConfigurable
|
||||
import im.vector.riotredesign.core.platform.VectorBaseFragment
|
||||
import im.vector.riotredesign.features.home.AvatarRenderer
|
||||
import im.vector.riotredesign.features.home.room.list.RoomListFragment
|
||||
import im.vector.riotredesign.features.home.room.list.RoomListParams
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.android.synthetic.main.fragment_selected_group.*
|
||||
|
||||
@Parcelize
|
||||
data class SelectedGroupParams(
|
||||
val groupId: String,
|
||||
val groupName: String,
|
||||
val groupAvatar: String
|
||||
) : Parcelable
|
||||
|
||||
class SelectedGroupFragment : VectorBaseFragment() {
|
||||
|
||||
private val selectedGroupParams: SelectedGroupParams by args()
|
||||
|
||||
override fun getLayoutResId(): Int {
|
||||
return R.layout.fragment_selected_group
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
if (savedInstanceState == null) {
|
||||
updateSelectedFragment(RoomListFragment.DisplayMode.HOME)
|
||||
toolbar.setTitle(RoomListFragment.DisplayMode.HOME.titleRes)
|
||||
}
|
||||
setupBottomNavigationView()
|
||||
setupToolbar()
|
||||
}
|
||||
|
||||
private fun setupToolbar() {
|
||||
val parentActivity = vectorBaseActivity
|
||||
if (parentActivity is ToolbarConfigurable) {
|
||||
parentActivity.configure(toolbar)
|
||||
}
|
||||
val toolbarLogoTarget = object : SimpleTarget<Drawable>() {
|
||||
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
|
||||
toolbar.logo = resource
|
||||
}
|
||||
}
|
||||
AvatarRenderer.render(
|
||||
requireContext(),
|
||||
GlideApp.with(this),
|
||||
selectedGroupParams.groupAvatar,
|
||||
selectedGroupParams.groupId,
|
||||
selectedGroupParams.groupName,
|
||||
toolbarLogoTarget
|
||||
)
|
||||
}
|
||||
|
||||
private fun setupBottomNavigationView() {
|
||||
bottomNavigationView.setOnNavigationItemSelectedListener {
|
||||
val displayMode = when {
|
||||
it.itemId == R.id.bottom_action_people -> RoomListFragment.DisplayMode.PEOPLE
|
||||
it.itemId == R.id.bottom_action_rooms -> RoomListFragment.DisplayMode.ROOMS
|
||||
else -> RoomListFragment.DisplayMode.HOME
|
||||
}
|
||||
updateSelectedFragment(displayMode)
|
||||
toolbar.setTitle(displayMode.titleRes)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSelectedFragment(displayMode: RoomListFragment.DisplayMode) {
|
||||
val roomListParams = RoomListParams(displayMode)
|
||||
val roomListFragment = RoomListFragment.newInstance(roomListParams)
|
||||
replaceChildFragment(roomListFragment, R.id.roomListContainer)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance(args: SelectedGroupParams): SelectedGroupFragment {
|
||||
return SelectedGroupFragment().apply {
|
||||
setArguments(args)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* 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.home.room.detail
|
||||
|
||||
import android.graphics.drawable.AnimationDrawable
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import im.vector.riotredesign.R
|
||||
import im.vector.riotredesign.core.platform.VectorBaseFragment
|
||||
import kotlinx.android.synthetic.main.fragment_loading_room_detail.*
|
||||
|
||||
class LoadingRoomDetailFragment : VectorBaseFragment() {
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance(): LoadingRoomDetailFragment {
|
||||
return LoadingRoomDetailFragment()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLayoutResId() = R.layout.fragment_loading_room_detail
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val background = animatedLogoImageView.background
|
||||
if (background is AnimationDrawable) {
|
||||
background.start()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
*
|
||||
* * 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.home.room.detail
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import im.vector.riotredesign.R
|
||||
import im.vector.riotredesign.core.extensions.replaceFragment
|
||||
import im.vector.riotredesign.core.platform.VectorBaseActivity
|
||||
|
||||
class RoomDetailActivity : VectorBaseActivity() {
|
||||
|
||||
override fun getLayoutRes(): Int {
|
||||
return R.layout.activity_room_detail
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
if (savedInstanceState == null) {
|
||||
val roomDetailArgs: RoomDetailArgs = intent?.extras?.getParcelable(EXTRA_ROOM_DETAIL_ARGS)
|
||||
?: return
|
||||
val roomDetailFragment = RoomDetailFragment.newInstance(roomDetailArgs)
|
||||
replaceFragment(roomDetailFragment, R.id.roomDetailContainer)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val EXTRA_ROOM_DETAIL_ARGS = "EXTRA_ROOM_DETAIL_ARGS"
|
||||
|
||||
fun newIntent(context: Context, roomDetailArgs: RoomDetailArgs): Intent {
|
||||
return Intent(context, RoomDetailActivity::class.java).apply {
|
||||
putExtra(EXTRA_ROOM_DETAIL_ARGS, roomDetailArgs)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -64,7 +64,6 @@ import im.vector.riotredesign.core.epoxy.LayoutManagerStateRestorer
|
|||
import im.vector.riotredesign.core.extensions.hideKeyboard
|
||||
import im.vector.riotredesign.core.extensions.observeEvent
|
||||
import im.vector.riotredesign.core.glide.GlideApp
|
||||
import im.vector.riotredesign.core.platform.ToolbarConfigurable
|
||||
import im.vector.riotredesign.core.platform.VectorBaseFragment
|
||||
import im.vector.riotredesign.core.utils.*
|
||||
import im.vector.riotredesign.features.autocomplete.command.AutocompleteCommandPresenter
|
||||
|
@ -170,7 +169,6 @@ class RoomDetailFragment :
|
|||
actionViewModel = ViewModelProviders.of(requireActivity()).get(ActionsHandler::class.java)
|
||||
bindScope(getOrCreateScope(HomeModule.ROOM_DETAIL_SCOPE))
|
||||
setupRecyclerView()
|
||||
setupToolbar()
|
||||
setupComposer()
|
||||
setupAttachmentButton()
|
||||
setupInviteView()
|
||||
|
@ -194,7 +192,7 @@ class RoomDetailFragment :
|
|||
if (resultCode == RESULT_OK && data != null) {
|
||||
when (requestCode) {
|
||||
REQUEST_FILES_REQUEST_CODE, TAKE_IMAGE_REQUEST_CODE -> handleMediaIntent(data)
|
||||
REACTION_SELECT_REQUEST_CODE -> {
|
||||
REACTION_SELECT_REQUEST_CODE -> {
|
||||
val eventId = data.getStringExtra(EmojiReactionPickerActivity.EXTRA_EVENT_ID)
|
||||
?: return
|
||||
val reaction = data.getStringExtra(EmojiReactionPickerActivity.EXTRA_REACTION_RESULT)
|
||||
|
@ -213,13 +211,6 @@ class RoomDetailFragment :
|
|||
|
||||
// PRIVATE METHODS *****************************************************************************
|
||||
|
||||
private fun setupToolbar() {
|
||||
val parentActivity = vectorBaseActivity
|
||||
if (parentActivity is ToolbarConfigurable) {
|
||||
parentActivity.configure(toolbar)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
val epoxyVisibilityTracker = EpoxyVisibilityTracker()
|
||||
epoxyVisibilityTracker.attach(recyclerView)
|
||||
|
@ -362,24 +353,24 @@ class RoomDetailFragment :
|
|||
private fun onSendChoiceClicked(dialogListItem: DialogListItem) {
|
||||
Timber.v("On send choice clicked: $dialogListItem")
|
||||
when (dialogListItem) {
|
||||
is DialogListItem.SendFile -> {
|
||||
is DialogListItem.SendFile -> {
|
||||
// launchFileIntent
|
||||
}
|
||||
is DialogListItem.SendVoice -> {
|
||||
is DialogListItem.SendVoice -> {
|
||||
//launchAudioRecorderIntent()
|
||||
}
|
||||
is DialogListItem.SendSticker -> {
|
||||
is DialogListItem.SendSticker -> {
|
||||
//startStickerPickerActivity()
|
||||
}
|
||||
is DialogListItem.TakePhotoVideo ->
|
||||
if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, requireActivity(), PERMISSION_REQUEST_CODE_LAUNCH_CAMERA)) {
|
||||
// launchCamera()
|
||||
}
|
||||
is DialogListItem.TakePhoto ->
|
||||
is DialogListItem.TakePhoto ->
|
||||
if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, requireActivity(), PERMISSION_REQUEST_CODE_LAUNCH_NATIVE_CAMERA)) {
|
||||
openCamera(requireActivity(), CAMERA_VALUE_TITLE, TAKE_IMAGE_REQUEST_CODE)
|
||||
}
|
||||
is DialogListItem.TakeVideo ->
|
||||
is DialogListItem.TakeVideo ->
|
||||
if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, requireActivity(), PERMISSION_REQUEST_CODE_LAUNCH_NATIVE_VIDEO_CAMERA)) {
|
||||
// launchNativeVideoRecorder()
|
||||
}
|
||||
|
@ -426,20 +417,20 @@ class RoomDetailFragment :
|
|||
private fun renderSendMessageResult(sendMessageResult: SendMessageResult) {
|
||||
when (sendMessageResult) {
|
||||
is SendMessageResult.MessageSent,
|
||||
is SendMessageResult.SlashCommandHandled -> {
|
||||
is SendMessageResult.SlashCommandHandled -> {
|
||||
// Clear composer
|
||||
composerEditText.text = null
|
||||
}
|
||||
is SendMessageResult.SlashCommandError -> {
|
||||
is SendMessageResult.SlashCommandError -> {
|
||||
displayCommandError(getString(R.string.command_problem_with_parameters, sendMessageResult.command.command))
|
||||
}
|
||||
is SendMessageResult.SlashCommandUnknown -> {
|
||||
is SendMessageResult.SlashCommandUnknown -> {
|
||||
displayCommandError(getString(R.string.unrecognized_command, sendMessageResult.command))
|
||||
}
|
||||
is SendMessageResult.SlashCommandResultOk -> {
|
||||
is SendMessageResult.SlashCommandResultOk -> {
|
||||
// Ignore
|
||||
}
|
||||
is SendMessageResult.SlashCommandResultError -> {
|
||||
is SendMessageResult.SlashCommandResultError -> {
|
||||
displayCommandError(sendMessageResult.throwable.localizedMessage)
|
||||
}
|
||||
is SendMessageResult.SlashCommandNotImplemented -> {
|
||||
|
@ -537,22 +528,22 @@ class RoomDetailFragment :
|
|||
it?.getContentIfNotHandled()?.let { actionData ->
|
||||
|
||||
when (actionData.actionId) {
|
||||
MessageMenuViewModel.ACTION_ADD_REACTION -> {
|
||||
MessageMenuViewModel.ACTION_ADD_REACTION -> {
|
||||
val eventId = actionData.data?.toString() ?: return
|
||||
startActivityForResult(EmojiReactionPickerActivity.intent(requireContext(), eventId), REACTION_SELECT_REQUEST_CODE)
|
||||
}
|
||||
MessageMenuViewModel.ACTION_COPY -> {
|
||||
MessageMenuViewModel.ACTION_COPY -> {
|
||||
//I need info about the current selected message :/
|
||||
copyToClipboard(requireContext(), actionData.data?.toString() ?: "", false)
|
||||
val snack = Snackbar.make(view!!, requireContext().getString(R.string.copied_to_clipboard), Snackbar.LENGTH_SHORT)
|
||||
snack.view.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.notification_accent_color))
|
||||
snack.show()
|
||||
}
|
||||
MessageMenuViewModel.ACTION_DELETE -> {
|
||||
MessageMenuViewModel.ACTION_DELETE -> {
|
||||
val eventId = actionData.data?.toString() ?: return
|
||||
roomDetailViewModel.process(RoomDetailActions.RedactAction(eventId, context?.getString(R.string.event_redacted_by_user_reason)))
|
||||
}
|
||||
MessageMenuViewModel.ACTION_SHARE -> {
|
||||
MessageMenuViewModel.ACTION_SHARE -> {
|
||||
//TODO current data communication is too limited
|
||||
//Need to now the media type
|
||||
actionData.data?.toString()?.let {
|
||||
|
@ -595,13 +586,13 @@ class RoomDetailFragment :
|
|||
.setPositiveButton(R.string.ok) { dialog, id -> dialog.cancel() }
|
||||
.show()
|
||||
}
|
||||
MessageMenuViewModel.ACTION_QUICK_REACT -> {
|
||||
MessageMenuViewModel.ACTION_QUICK_REACT -> {
|
||||
//eventId,ClickedOn,Opposite
|
||||
(actionData.data as? Triple<String, String, String>)?.let { (eventId, clickedOn, opposite) ->
|
||||
roomDetailViewModel.process(RoomDetailActions.UpdateQuickReactAction(eventId, clickedOn, opposite))
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
else -> {
|
||||
Toast.makeText(context, "Action ${actionData.actionId} not implemented", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
package im.vector.riotredesign.features.home.room.list
|
||||
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.os.Parcelable
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Incomplete
|
||||
|
@ -29,21 +29,35 @@ import im.vector.matrix.android.api.session.room.model.RoomSummary
|
|||
import im.vector.riotredesign.R
|
||||
import im.vector.riotredesign.core.epoxy.LayoutManagerStateRestorer
|
||||
import im.vector.riotredesign.core.extensions.observeEvent
|
||||
import im.vector.riotredesign.core.extensions.setupAsSearch
|
||||
import im.vector.riotredesign.core.platform.StateView
|
||||
import im.vector.riotredesign.core.platform.VectorBaseFragment
|
||||
import im.vector.riotredesign.features.home.HomeModule
|
||||
import im.vector.riotredesign.features.home.HomeNavigator
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.android.synthetic.main.fragment_room_list.*
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.android.scope.ext.android.bindScope
|
||||
import org.koin.android.scope.ext.android.getOrCreateScope
|
||||
|
||||
@Parcelize
|
||||
data class RoomListParams(
|
||||
val displayMode: RoomListFragment.DisplayMode
|
||||
) : Parcelable
|
||||
|
||||
|
||||
class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Callback {
|
||||
|
||||
enum class DisplayMode(@StringRes val titleRes: Int) {
|
||||
HOME(R.string.bottom_action_home),
|
||||
PEOPLE(R.string.bottom_action_people),
|
||||
ROOMS(R.string.bottom_action_rooms)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun newInstance(): RoomListFragment {
|
||||
return RoomListFragment()
|
||||
fun newInstance(roomListParams: RoomListParams): RoomListFragment {
|
||||
return RoomListFragment().apply {
|
||||
setArguments(roomListParams)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,7 +71,6 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Callback {
|
|||
super.onActivityCreated(savedInstanceState)
|
||||
bindScope(getOrCreateScope(HomeModule.ROOM_LIST_SCOPE))
|
||||
setupRecyclerView()
|
||||
setupFilterView()
|
||||
roomListViewModel.subscribe { renderState(it) }
|
||||
roomListViewModel.openRoomLiveData.observeEvent(this) {
|
||||
homeNavigator.openRoomDetail(it, null)
|
||||
|
@ -74,19 +87,6 @@ class RoomListFragment : VectorBaseFragment(), RoomSummaryController.Callback {
|
|||
epoxyRecyclerView.setController(roomController)
|
||||
}
|
||||
|
||||
private fun setupFilterView() {
|
||||
filterRoomView.setupAsSearch()
|
||||
filterRoomView.addTextChangedListener(object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable?) = Unit
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit
|
||||
|
||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
||||
roomListViewModel.accept(RoomListActions.FilterRooms(s))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun renderState(state: RoomListViewState) {
|
||||
when (state.asyncRooms) {
|
||||
is Incomplete -> renderLoading()
|
||||
|
|
|
@ -30,6 +30,7 @@ import im.vector.matrix.android.api.session.room.model.tag.RoomTag
|
|||
import im.vector.matrix.rx.rx
|
||||
import im.vector.riotredesign.core.platform.VectorViewModel
|
||||
import im.vector.riotredesign.core.utils.LiveEvent
|
||||
import im.vector.riotredesign.features.home.group.ALL_COMMUNITIES_GROUP_ID
|
||||
import im.vector.riotredesign.features.home.group.SelectedGroupStore
|
||||
import im.vector.riotredesign.features.home.room.VisibleRoomStore
|
||||
import io.reactivex.Observable
|
||||
|
@ -118,7 +119,7 @@ class RoomListViewModel(initialState: RoomListViewState,
|
|||
val filteredDirectRooms = filteredRooms
|
||||
.filter { it.isDirect }
|
||||
.filter {
|
||||
if (selectedGroup == null) {
|
||||
if (selectedGroup == null || selectedGroup.groupId == ALL_COMMUNITIES_GROUP_ID) {
|
||||
true
|
||||
} else {
|
||||
it.otherMemberIds
|
||||
|
@ -130,7 +131,8 @@ class RoomListViewModel(initialState: RoomListViewState,
|
|||
val filteredGroupRooms = filteredRooms
|
||||
.filter { !it.isDirect }
|
||||
.filter {
|
||||
selectedGroup?.roomIds?.contains(it.roomId) ?: true
|
||||
selectedGroup?.groupId == ALL_COMMUNITIES_GROUP_ID
|
||||
|| selectedGroup?.roomIds?.contains(it.roomId) ?: true
|
||||
}
|
||||
buildRoomSummaries(filteredDirectRooms + filteredGroupRooms)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/roomDetailContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
</FrameLayout>
|
|
@ -4,8 +4,7 @@
|
|||
<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">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.airbnb.epoxy.EpoxyRecyclerView
|
||||
android:id="@+id/epoxyRecyclerView"
|
||||
|
|
|
@ -1,23 +1,68 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/stateView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/groupListFragmentContainer"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/homeDrawerHeader"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/homeDrawerHeaderAvatarView"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:layout_marginTop="24dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@tools:sample/avatars" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/homeDrawerUsernameView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:textColor="@android:color/white"
|
||||
app:layout_constraintStart_toStartOf="@+id/homeDrawerHeaderAvatarView"
|
||||
app:layout_constraintTop_toBottomOf="@+id/homeDrawerHeaderAvatarView"
|
||||
tools:text="@tools:sample/full_names" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/homeDrawerUserIdView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:textColor="@android:color/white"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@+id/homeDrawerUsernameView"
|
||||
app:layout_constraintTop_toBottomOf="@+id/homeDrawerUsernameView"
|
||||
tools:text="@tools:sample/full_names" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/homeDrawerHeaderSettingsView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/homeDrawerUserIdView" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/roomListFragmentContainer"
|
||||
android:id="@+id/homeDrawerGroupListContainer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@android:color/white"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/groupListFragmentContainer"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/homeDrawerHeader" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,53 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
<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/pale_grey">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/filterRoomView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="@drawable/bg_search_edit_text"
|
||||
android:drawableStart="@drawable/ic_search_white"
|
||||
android:drawableLeft="@drawable/ic_search_white"
|
||||
android:drawablePadding="8dp"
|
||||
android:drawableTint="#9fa9ba"
|
||||
android:hint="@string/home_filter_placeholder_rooms"
|
||||
android:lines="1"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/stateView"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
<com.airbnb.epoxy.EpoxyRecyclerView
|
||||
android:id="@+id/epoxyRecyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<im.vector.riotredesign.core.platform.StateView
|
||||
android:id="@+id/stateView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginEnd="0dp"
|
||||
android:layout_marginRight="0dp"
|
||||
android:layout_marginBottom="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/filterRoomView">
|
||||
|
||||
<com.airbnb.epoxy.EpoxyRecyclerView
|
||||
android:id="@+id/epoxyRecyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</im.vector.riotredesign.core.platform.StateView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</im.vector.riotredesign.core.platform.StateView>
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/VectorToolbarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:contentInsetStartWithNavigation="0dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
|
||||
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/roomListContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/bottomNavigationView"
|
||||
app:layout_constraintTop_toBottomOf="@+id/toolbar" />
|
||||
|
||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
android:id="@+id/bottomNavigationView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/colorPrimary"
|
||||
app:itemIconTint="@android:color/white"
|
||||
app:itemTextColor="@color/home_bottom_nav_view_tint"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:menu='@menu/selected_group_navigation' />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,22 +1,48 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<im.vector.riotredesign.core.platform.CheckableFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/itemGroupLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="56dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="8dp">
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/groupAvatarImageView"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center"
|
||||
android:duplicateParentState="true"
|
||||
android:foreground="@drawable/fg_group_item"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@tools:sample/avatars" />
|
||||
|
||||
</im.vector.riotredesign.core.platform.CheckableFrameLayout>
|
||||
<TextView
|
||||
android:id="@+id/groupNameView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="32dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/groupAvatarImageView"
|
||||
app:layout_constraintEnd_toStartOf="@+id/groupAvatarChevron"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toEndOf="@+id/groupAvatarImageView"
|
||||
app:layout_constraintTop_toTopOf="@+id/groupAvatarImageView"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/groupAvatarChevron"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_material_chevron_right_black"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/bottom_action_home"
|
||||
android:contentDescription="@string/bottom_action_home"
|
||||
android:enabled="true"
|
||||
android:icon="@drawable/ic_home_black_24dp"
|
||||
android:title="" />
|
||||
|
||||
|
||||
<item
|
||||
android:id="@+id/bottom_action_people"
|
||||
android:contentDescription="@string/bottom_action_people"
|
||||
android:enabled="true"
|
||||
android:icon="@drawable/ic_person_black_24dp"
|
||||
android:title="" />
|
||||
|
||||
<item
|
||||
android:id="@+id/bottom_action_rooms"
|
||||
android:contentDescription="@string/bottom_action_rooms"
|
||||
android:enabled="true"
|
||||
android:icon="@drawable/riot_tab_rooms"
|
||||
android:title="" />
|
||||
|
||||
</menu>
|
Loading…
Reference in New Issue