mirror of
https://github.com/vector-im/riotX-android
synced 2025-10-06 00:02:48 +02:00
Compare commits
17 Commits
bugfix/eri
...
feature/us
Author | SHA1 | Date | |
---|---|---|---|
|
16a1cf2d42 | ||
|
1f2de129a1 | ||
|
2ba5ea7674 | ||
|
488083ca8c | ||
|
e53d39b82e | ||
|
063241b5a5 | ||
|
d6dc4b9a18 | ||
|
7d0f5aa49e | ||
|
071db7a4d8 | ||
|
2c747cc847 | ||
|
87322ce8b0 | ||
|
ad9f67b3bd | ||
|
3ae0586dac | ||
|
19b411776a | ||
|
5286e6983c | ||
|
ddbc2b0ade | ||
|
5f79530c4c |
@@ -112,7 +112,7 @@ android {
|
||||
ndkVersion "21.3.6528147"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "im.vector.app"
|
||||
applicationId "im.vector.app.tabs"
|
||||
// Set to API 21: see #405
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
@@ -186,7 +186,7 @@ android {
|
||||
buildTypes {
|
||||
debug {
|
||||
applicationIdSuffix ".debug"
|
||||
resValue "string", "app_name", "Element dbg"
|
||||
resValue "string", "app_name", "Element Tabs"
|
||||
|
||||
resValue "bool", "debug_mode", "true"
|
||||
buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false"
|
||||
@@ -195,7 +195,7 @@ android {
|
||||
}
|
||||
|
||||
release {
|
||||
resValue "string", "app_name", "Element (Riot.im)"
|
||||
resValue "string", "app_name", "Element Grid"
|
||||
|
||||
resValue "bool", "debug_mode", "false"
|
||||
buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false"
|
||||
|
@@ -10,7 +10,7 @@
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:912726360885:android:4ef8f3a0021e774d",
|
||||
"android_client_info": {
|
||||
"package_name": "im.vector.app.debug"
|
||||
"package_name": "im.vector.app.tabs.debug"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
|
@@ -10,7 +10,7 @@
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:912726360885:android:4ef8f3a0021e774d",
|
||||
"android_client_info": {
|
||||
"package_name": "im.vector.app"
|
||||
"package_name": "im.vector.app.tabs"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
|
@@ -52,6 +52,7 @@ import im.vector.app.features.home.LoadingFragment
|
||||
import im.vector.app.features.home.room.breadcrumbs.BreadcrumbsFragment
|
||||
import im.vector.app.features.home.room.detail.RoomDetailFragment
|
||||
import im.vector.app.features.home.room.list.RoomListFragment
|
||||
import im.vector.app.features.home.room.list.tabs.RoomListTabsFragment
|
||||
import im.vector.app.features.login.LoginCaptchaFragment
|
||||
import im.vector.app.features.login.LoginFragment
|
||||
import im.vector.app.features.login.LoginGenericTextInputFormFragment
|
||||
@@ -124,6 +125,11 @@ interface FragmentModule {
|
||||
@FragmentKey(RoomListFragment::class)
|
||||
fun bindRoomListFragment(fragment: RoomListFragment): Fragment
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(RoomListTabsFragment::class)
|
||||
fun bindRoomListTabsFragment(fragment: RoomListTabsFragment): Fragment
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(LocalePickerFragment::class)
|
||||
|
@@ -123,7 +123,7 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable, UnknownDeviceDet
|
||||
drawerLayout.closeDrawer(GravityCompat.START)
|
||||
replaceFragment(R.id.homeDetailFragmentContainer, HomeDetailFragment::class.java)
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
.disposeOnDestroy()
|
||||
|
||||
|
@@ -25,4 +25,5 @@ sealed class HomeActivitySharedAction : VectorSharedAction {
|
||||
object OpenDrawer : HomeActivitySharedAction()
|
||||
object CloseDrawer : HomeActivitySharedAction()
|
||||
object OpenGroup : HomeActivitySharedAction()
|
||||
data class OnDisplayModeSelected(val displayMode: RoomListDisplayMode): HomeActivitySharedAction()
|
||||
}
|
||||
|
@@ -19,5 +19,5 @@ package im.vector.app.features.home
|
||||
import im.vector.app.core.platform.VectorViewModelAction
|
||||
|
||||
sealed class HomeDetailAction : VectorViewModelAction {
|
||||
data class SwitchDisplayMode(val displayMode: RoomListDisplayMode) : HomeDetailAction()
|
||||
data class SwitchDisplayMode(val displayMode: HomeDisplayMode) : HomeDetailAction()
|
||||
}
|
||||
|
@@ -18,13 +18,19 @@ package im.vector.app.features.home
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.forEach
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.lifecycle.Observer
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.google.android.material.badge.BadgeDrawable
|
||||
import com.google.android.material.behavior.HideBottomViewOnScrollBehavior
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.addFragment
|
||||
import im.vector.app.core.extensions.commitTransaction
|
||||
import im.vector.app.core.glide.GlideApp
|
||||
import im.vector.app.core.platform.ToolbarConfigurable
|
||||
@@ -33,11 +39,14 @@ import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.core.ui.views.ActiveCallView
|
||||
import im.vector.app.core.ui.views.ActiveCallViewHolder
|
||||
import im.vector.app.core.ui.views.KeysBackupBanner
|
||||
import im.vector.app.core.utils.DimensionConverter
|
||||
import im.vector.app.features.call.SharedActiveCallViewModel
|
||||
import im.vector.app.features.call.VectorCallActivity
|
||||
import im.vector.app.features.call.WebRtcPeerConnectionManager
|
||||
import im.vector.app.features.home.room.list.RoomListFragment
|
||||
import im.vector.app.features.home.room.list.RoomListParams
|
||||
import im.vector.app.features.home.room.list.tabs.RoomListTabsFragment
|
||||
import im.vector.app.features.home.room.list.widget.FabMenuView
|
||||
import im.vector.app.features.popup.PopupAlertManager
|
||||
import im.vector.app.features.popup.VerificationVectorAlert
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
@@ -63,8 +72,9 @@ class HomeDetailFragment @Inject constructor(
|
||||
private val avatarRenderer: AvatarRenderer,
|
||||
private val alertManager: PopupAlertManager,
|
||||
private val webRtcPeerConnectionManager: WebRtcPeerConnectionManager,
|
||||
private val vectorPreferences: VectorPreferences
|
||||
) : VectorBaseFragment(), KeysBackupBanner.Delegate, ActiveCallView.Callback, ServerBackupStatusViewModel.Factory {
|
||||
private val vectorPreferences: VectorPreferences,
|
||||
private val dimensionConverter: DimensionConverter
|
||||
) : VectorBaseFragment(), KeysBackupBanner.Delegate, ActiveCallView.Callback, ServerBackupStatusViewModel.Factory, FabMenuView.Listener {
|
||||
|
||||
private val viewModel: HomeDetailViewModel by fragmentViewModel()
|
||||
private val unknownDeviceDetectorSharedViewModel: UnknownDeviceDetectorSharedViewModel by activityViewModel()
|
||||
@@ -81,7 +91,7 @@ class HomeDetailFragment @Inject constructor(
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
sharedActionViewModel = activityViewModelProvider.get(HomeSharedActionViewModel::class.java)
|
||||
sharedCallActionViewModel = activityViewModelProvider.get(SharedActiveCallViewModel::class.java)
|
||||
|
||||
setupCreateRoomButton()
|
||||
setupBottomNavigationView()
|
||||
setupToolbar()
|
||||
setupKeysBackupBanner()
|
||||
@@ -95,7 +105,9 @@ class HomeDetailFragment @Inject constructor(
|
||||
viewModel.selectSubscribe(this, HomeDetailViewState::groupSummary) { groupSummary ->
|
||||
onGroupChange(groupSummary.orNull())
|
||||
}
|
||||
|
||||
viewModel.selectSubscribe(this, HomeDetailViewState::displayMode) { displayMode ->
|
||||
if (vectorPreferences.labUseTabNavigation()) return@selectSubscribe
|
||||
switchDisplayMode(displayMode)
|
||||
}
|
||||
|
||||
@@ -117,12 +129,74 @@ class HomeDetailFragment @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
sharedActionViewModel.observe()
|
||||
.subscribe {
|
||||
when (it) {
|
||||
is HomeActivitySharedAction.OnDisplayModeSelected -> renderDisplayMode(it.displayMode)
|
||||
}
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
|
||||
sharedCallActionViewModel
|
||||
.activeCall
|
||||
.observe(viewLifecycleOwner, Observer {
|
||||
activeCallViewHolder.updateCall(it, webRtcPeerConnectionManager)
|
||||
invalidateOptionsMenu()
|
||||
})
|
||||
|
||||
if (vectorPreferences.labUseTabNavigation()) {
|
||||
addFragment(R.id.roomListContainer, RoomListTabsFragment::class.java)
|
||||
bottomNavigationView.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
createChatFabMenu.listener = null
|
||||
}
|
||||
|
||||
private fun renderDisplayMode(displayMode: RoomListDisplayMode) {
|
||||
when (displayMode) {
|
||||
RoomListDisplayMode.ALL,
|
||||
RoomListDisplayMode.NOTIFICATIONS,
|
||||
RoomListDisplayMode.FAVORITES,
|
||||
RoomListDisplayMode.LOW_PRIORITY,
|
||||
RoomListDisplayMode.INVITES -> {
|
||||
createChatFabMenu.getHideBottomViewOnScrollBehavior().slideUp(createChatFabMenu)
|
||||
createChatFabMenu.show()
|
||||
createChatRoomButton.isVisible = false
|
||||
createGroupRoomButton.isVisible = false
|
||||
}
|
||||
RoomListDisplayMode.PEOPLE -> {
|
||||
createChatFabMenu.isVisible = false
|
||||
createChatRoomButton.isVisible = true
|
||||
createChatRoomButton.getHideBottomViewOnScrollBehavior().slideUp(createChatRoomButton)
|
||||
createChatRoomButton.show()
|
||||
createGroupRoomButton.isVisible = false
|
||||
}
|
||||
RoomListDisplayMode.ROOMS -> {
|
||||
createChatFabMenu.isVisible = false
|
||||
createChatRoomButton.isVisible = false
|
||||
createGroupRoomButton.isVisible = true
|
||||
createGroupRoomButton.getHideBottomViewOnScrollBehavior().slideUp(createGroupRoomButton)
|
||||
createGroupRoomButton.show()
|
||||
}
|
||||
else -> {
|
||||
createChatFabMenu.isVisible = false
|
||||
createChatRoomButton.isVisible = false
|
||||
createGroupRoomButton.isVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupCreateRoomButton() {
|
||||
createChatFabMenu.listener = this
|
||||
createChatRoomButton.debouncedClicks {
|
||||
createDirectChat()
|
||||
}
|
||||
createGroupRoomButton.debouncedClicks {
|
||||
openRoomDirectory()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
@@ -131,17 +205,46 @@ class HomeDetailFragment @Inject constructor(
|
||||
checkNotificationTabStatus()
|
||||
}
|
||||
|
||||
private fun checkNotificationTabStatus() {
|
||||
val wasVisible = bottomNavigationView.menu.findItem(R.id.bottom_action_notification).isVisible
|
||||
bottomNavigationView.menu.findItem(R.id.bottom_action_notification).isVisible = vectorPreferences.labAddNotificationTab()
|
||||
if (wasVisible && !vectorPreferences.labAddNotificationTab()) {
|
||||
// As we hide it check if it's not the current item!
|
||||
withState(viewModel) {
|
||||
if (it.displayMode.toMenuId() == R.id.bottom_action_notification) {
|
||||
viewModel.handle(HomeDetailAction.SwitchDisplayMode(RoomListDisplayMode.PEOPLE))
|
||||
}
|
||||
private fun checkNotificationTabStatus() = withState(viewModel) { state ->
|
||||
bottomNavigationView.menu.forEach { menuItem ->
|
||||
menuItem.isVisible = state.tabList.indexOfFirst { it.toMenuId() == menuItem.itemId } != -1
|
||||
}
|
||||
|
||||
if (vectorPreferences.labUseTabNavigation()) {
|
||||
addFragment(R.id.roomListContainer, RoomListTabsFragment::class.java)
|
||||
bottomNavigationView.isVisible = false
|
||||
createGroupRoomButton.updateLayoutParams<CoordinatorLayout.LayoutParams> {
|
||||
this.bottomMargin = dimensionConverter.dpToPx(16)
|
||||
}
|
||||
createChatRoomButton.updateLayoutParams<CoordinatorLayout.LayoutParams> {
|
||||
this.bottomMargin = dimensionConverter.dpToPx(16)
|
||||
}
|
||||
createChatFabMenu.updateLayoutParams<CoordinatorLayout.LayoutParams> {
|
||||
this.bottomMargin = dimensionConverter.dpToPx(0)
|
||||
}
|
||||
} else {
|
||||
bottomNavigationView.isVisible = true
|
||||
switchDisplayMode(state.displayMode)
|
||||
createGroupRoomButton.updateLayoutParams<CoordinatorLayout.LayoutParams> {
|
||||
this.bottomMargin = dimensionConverter.dpToPx(64)
|
||||
}
|
||||
createChatRoomButton.updateLayoutParams<CoordinatorLayout.LayoutParams> {
|
||||
this.bottomMargin = dimensionConverter.dpToPx(64)
|
||||
}
|
||||
createChatFabMenu.updateLayoutParams<CoordinatorLayout.LayoutParams> {
|
||||
this.bottomMargin = dimensionConverter.dpToPx(48)
|
||||
}
|
||||
}
|
||||
// val wasVisible = bottomNavigationView.menu.findItem(R.id.bottom_action_notification).isVisible
|
||||
// bottomNavigationView.menu.findItem(R.id.bottom_action_notification).isVisible = vectorPreferences.labAddNotificationTab()
|
||||
// if (wasVisible && !vectorPreferences.labAddNotificationTab()) {
|
||||
// // As we hide it check if it's not the current item!
|
||||
// withState(viewModel) {
|
||||
// if (it.displayMode.toMenuId() == R.id.bottom_action_notification) {
|
||||
// viewModel.handle(HomeDetailAction.SwitchDisplayMode(HomeDisplayMode.CHATS))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
private fun promptForNewUnknownDevices(uid: String, state: UnknownDevicesState, newest: DeviceInfo) {
|
||||
@@ -205,6 +308,7 @@ class HomeDetailFragment @Inject constructor(
|
||||
groupSummary?.let {
|
||||
// Use GlideApp with activity context to avoid the glideRequests to be paused
|
||||
avatarRenderer.render(it.toMatrixItem(), groupToolbarAvatarImageView, GlideApp.with(requireActivity()))
|
||||
groupToolbarTitleView.text = it.displayName
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,9 +349,12 @@ class HomeDetailFragment @Inject constructor(
|
||||
bottomNavigationView.menu.findItem(R.id.bottom_action_notification).isVisible = vectorPreferences.labAddNotificationTab()
|
||||
bottomNavigationView.setOnNavigationItemSelectedListener {
|
||||
val displayMode = when (it.itemId) {
|
||||
R.id.bottom_action_people -> RoomListDisplayMode.PEOPLE
|
||||
R.id.bottom_action_rooms -> RoomListDisplayMode.ROOMS
|
||||
else -> RoomListDisplayMode.NOTIFICATIONS
|
||||
R.id.bottom_action_chats -> HomeDisplayMode.CHATS
|
||||
// R.id.bottom_action_you -> HomeDisplayMode.YOU
|
||||
R.id.bottom_action_favourites -> HomeDisplayMode.FAVORITES
|
||||
R.id.bottom_action_people -> HomeDisplayMode.PEOPLE
|
||||
R.id.bottom_action_rooms -> HomeDisplayMode.ROOMS
|
||||
else -> HomeDisplayMode.NOTIFICATIONS
|
||||
}
|
||||
viewModel.handle(HomeDetailAction.SwitchDisplayMode(displayMode))
|
||||
true
|
||||
@@ -265,12 +372,12 @@ class HomeDetailFragment @Inject constructor(
|
||||
// }
|
||||
}
|
||||
|
||||
private fun switchDisplayMode(displayMode: RoomListDisplayMode) {
|
||||
private fun switchDisplayMode(displayMode: HomeDisplayMode) {
|
||||
groupToolbarTitleView.setText(displayMode.titleRes)
|
||||
updateSelectedFragment(displayMode)
|
||||
}
|
||||
|
||||
private fun updateSelectedFragment(displayMode: RoomListDisplayMode) {
|
||||
private fun updateSelectedFragment(displayMode: HomeDisplayMode) {
|
||||
val fragmentTag = "FRAGMENT_TAG_${displayMode.name}"
|
||||
val fragmentToShow = childFragmentManager.findFragmentByTag(fragmentTag)
|
||||
childFragmentManager.commitTransaction {
|
||||
@@ -280,8 +387,16 @@ class HomeDetailFragment @Inject constructor(
|
||||
detach(it)
|
||||
}
|
||||
if (fragmentToShow == null) {
|
||||
val params = RoomListParams(displayMode)
|
||||
// if (displayMode == HomeDisplayMode.CHATS) {
|
||||
// add(R.id.roomListContainer, RoomListTabsFragment::class.java, Bundle.EMPTY, fragmentTag)
|
||||
// }
|
||||
// else if (displayMode == HomeDisplayMode.YOU) {
|
||||
// add(R.id.roomListContainer, VectorSettingsGeneralFragment::class.java, Bundle.EMPTY, fragmentTag)
|
||||
// }
|
||||
// else {
|
||||
val params = RoomListParams(displayMode.toRoomMode())
|
||||
add(R.id.roomListContainer, RoomListFragment::class.java, params.toMvRxBundle(), fragmentTag)
|
||||
// }
|
||||
} else {
|
||||
attach(fragmentToShow)
|
||||
}
|
||||
@@ -302,9 +417,9 @@ class HomeDetailFragment @Inject constructor(
|
||||
|
||||
override fun invalidate() = withState(viewModel) {
|
||||
Timber.v(it.toString())
|
||||
bottomNavigationView.getOrCreateBadge(R.id.bottom_action_people).render(it.notificationCountPeople, it.notificationHighlightPeople)
|
||||
bottomNavigationView.getOrCreateBadge(R.id.bottom_action_rooms).render(it.notificationCountRooms, it.notificationHighlightRooms)
|
||||
bottomNavigationView.getOrCreateBadge(R.id.bottom_action_notification).render(it.notificationCountCatchup, it.notificationHighlightCatchup)
|
||||
// bottomNavigationView.getOrCreateBadge(R.id.bottom_action_people).render(it.notificationCountPeople, it.notificationHighlightPeople)
|
||||
// bottomNavigationView.getOrCreateBadge(R.id.bottom_action_rooms).render(it.notificationCountRooms, it.notificationHighlightRooms)
|
||||
// bottomNavigationView.getOrCreateBadge(R.id.bottom_action_notification).render(it.notificationCountCatchup, it.notificationHighlightCatchup)
|
||||
syncStateView.render(it.syncState)
|
||||
}
|
||||
|
||||
@@ -320,10 +435,28 @@ class HomeDetailFragment @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun RoomListDisplayMode.toMenuId() = when (this) {
|
||||
RoomListDisplayMode.PEOPLE -> R.id.bottom_action_people
|
||||
RoomListDisplayMode.ROOMS -> R.id.bottom_action_rooms
|
||||
else -> R.id.bottom_action_notification
|
||||
// private fun RoomListDisplayMode.toMenuId() = when (this) {
|
||||
// // RoomListDisplayMode.PEOPLE -> R.id.bottom_action_people
|
||||
// // RoomListDisplayMode.ROOMS -> R.id.bottom_action_rooms
|
||||
// else -> R.id.bottom_action_notification
|
||||
// }
|
||||
|
||||
private fun HomeDisplayMode.toMenuId() = when (this) {
|
||||
HomeDisplayMode.CHATS -> R.id.bottom_action_chats
|
||||
HomeDisplayMode.FAVORITES -> R.id.bottom_action_favourites
|
||||
HomeDisplayMode.ROOMS -> R.id.bottom_action_rooms
|
||||
HomeDisplayMode.PEOPLE -> R.id.bottom_action_people
|
||||
HomeDisplayMode.NOTIFICATIONS -> R.id.bottom_action_notification
|
||||
// HomeDisplayMode.YOU -> R.id.bottom_action_you
|
||||
}
|
||||
|
||||
private fun HomeDisplayMode.toRoomMode() = when (this) {
|
||||
HomeDisplayMode.CHATS -> RoomListDisplayMode.ALL
|
||||
HomeDisplayMode.FAVORITES -> RoomListDisplayMode.FAVORITES
|
||||
HomeDisplayMode.NOTIFICATIONS -> RoomListDisplayMode.NOTIFICATIONS
|
||||
HomeDisplayMode.ROOMS -> RoomListDisplayMode.ROOMS
|
||||
HomeDisplayMode.PEOPLE -> RoomListDisplayMode.PEOPLE
|
||||
// else -> RoomListDisplayMode.ROOMS
|
||||
}
|
||||
|
||||
override fun onTapToReturnToCall() {
|
||||
@@ -342,7 +475,19 @@ class HomeDetailFragment @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override fun openRoomDirectory(initialFilter: String) {
|
||||
navigator.openRoomDirectory(requireActivity(), initialFilter)
|
||||
}
|
||||
|
||||
override fun createDirectChat() {
|
||||
navigator.openCreateDirectRoom(requireActivity())
|
||||
}
|
||||
|
||||
override fun create(initialState: ServerBackupStatusViewState): ServerBackupStatusViewModel {
|
||||
return serverBackupStatusViewModelFactory.create(initialState)
|
||||
}
|
||||
|
||||
private fun View.getHideBottomViewOnScrollBehavior(): HideBottomViewOnScrollBehavior<View> {
|
||||
return (layoutParams as CoordinatorLayout.LayoutParams).behavior as HideBottomViewOnScrollBehavior
|
||||
}
|
||||
}
|
||||
|
@@ -21,7 +21,6 @@ import com.airbnb.mvrx.MvRxViewModelFactory
|
||||
import com.airbnb.mvrx.ViewModelContext
|
||||
import com.squareup.inject.assisted.Assisted
|
||||
import com.squareup.inject.assisted.AssistedInject
|
||||
import im.vector.app.core.di.HasScreenInjector
|
||||
import im.vector.app.core.platform.EmptyViewEvents
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
@@ -52,9 +51,10 @@ class HomeDetailViewModel @AssistedInject constructor(@Assisted initialState: Ho
|
||||
companion object : MvRxViewModelFactory<HomeDetailViewModel, HomeDetailViewState> {
|
||||
|
||||
override fun initialState(viewModelContext: ViewModelContext): HomeDetailViewState? {
|
||||
val uiStateRepository = (viewModelContext.activity as HasScreenInjector).injector().uiStateRepository()
|
||||
// val uiStateRepository = (viewModelContext.activity as HasScreenInjector).injector().uiStateRepository()
|
||||
// TODO
|
||||
return HomeDetailViewState(
|
||||
displayMode = uiStateRepository.getDisplayMode()
|
||||
displayMode = HomeDisplayMode.CHATS // uiStateRepository.getDisplayMode()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ class HomeDetailViewModel @AssistedInject constructor(@Assisted initialState: Ho
|
||||
copy(displayMode = action.displayMode)
|
||||
}
|
||||
|
||||
uiStateRepository.storeDisplayMode(action.displayMode)
|
||||
// uiStateRepository.storeDisplayMode(action.displayMode)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -27,7 +27,8 @@ import org.matrix.android.sdk.api.session.sync.SyncState
|
||||
data class HomeDetailViewState(
|
||||
val groupSummary: Option<GroupSummary> = Option.empty(),
|
||||
val asyncRooms: Async<List<RoomSummary>> = Uninitialized,
|
||||
val displayMode: RoomListDisplayMode = RoomListDisplayMode.PEOPLE,
|
||||
val displayMode: HomeDisplayMode = HomeDisplayMode.CHATS,
|
||||
val tabList: List<HomeDisplayMode> = listOf(HomeDisplayMode.CHATS, HomeDisplayMode.FAVORITES, HomeDisplayMode.ROOMS, HomeDisplayMode.PEOPLE),
|
||||
val notificationCountCatchup: Int = 0,
|
||||
val notificationHighlightCatchup: Boolean = false,
|
||||
val notificationCountPeople: Int = 0,
|
||||
|
@@ -17,9 +17,13 @@
|
||||
package im.vector.app.features.home
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.HandlerThread
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import im.vector.app.features.home.room.detail.timeline.EpoxyControllerDiffHandler
|
||||
import im.vector.app.features.home.room.detail.timeline.EpoxyControllerModelHandler
|
||||
import im.vector.app.features.home.room.detail.timeline.TimelineEventControllerHandler
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.EpoxyHandlerHelper
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.TimelineAsyncHelper
|
||||
|
||||
@Module
|
||||
@@ -31,4 +35,18 @@ object HomeModule {
|
||||
fun providesTimelineBackgroundHandler(): Handler {
|
||||
return TimelineAsyncHelper.getBackgroundHandler()
|
||||
}
|
||||
|
||||
@Provides
|
||||
@JvmStatic
|
||||
@EpoxyControllerModelHandler
|
||||
fun providesEpoxyControllerModelHandler(): Handler {
|
||||
return EpoxyHandlerHelper.modelBuildingHandler
|
||||
}
|
||||
|
||||
@Provides
|
||||
@JvmStatic
|
||||
@EpoxyControllerDiffHandler
|
||||
fun providesEpoxyControllerDiffHandler(): Handler {
|
||||
return EpoxyHandlerHelper.diffingHandler
|
||||
}
|
||||
}
|
||||
|
@@ -19,8 +19,21 @@ package im.vector.app.features.home
|
||||
import androidx.annotation.StringRes
|
||||
import im.vector.app.R
|
||||
|
||||
enum class RoomListDisplayMode(@StringRes val titleRes: Int) {
|
||||
enum class HomeDisplayMode(@StringRes val titleRes: Int) {
|
||||
CHATS(R.string.home_bottom_tab_chats),
|
||||
NOTIFICATIONS(R.string.bottom_action_notification),
|
||||
FAVORITES(R.string.room_recents_favourites),
|
||||
PEOPLE(R.string.bottom_action_people_x),
|
||||
ROOMS(R.string.bottom_action_rooms),
|
||||
// YOU(R.string.home_bottom_tab_you),
|
||||
}
|
||||
|
||||
enum class RoomListDisplayMode(@StringRes val titleRes: Int) {
|
||||
ALL(R.string.room_list_tabs_all),
|
||||
FAVORITES(R.string.room_recents_favourites),
|
||||
NOTIFICATIONS(R.string.bottom_action_notification),
|
||||
LOW_PRIORITY(R.string.room_recents_low_priority),
|
||||
INVITES(R.string.invitations_header),
|
||||
PEOPLE(R.string.bottom_action_people_x),
|
||||
ROOMS(R.string.bottom_action_rooms),
|
||||
FILTERED(/* Not used */ 0)
|
||||
|
@@ -63,8 +63,10 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
|
||||
private val timelineMediaSizeProvider: TimelineMediaSizeProvider,
|
||||
private val mergedHeaderItemFactory: MergedHeaderItemFactory,
|
||||
@TimelineEventControllerHandler
|
||||
private val backgroundHandler: Handler
|
||||
) : EpoxyController(backgroundHandler, backgroundHandler), Timeline.Listener, EpoxyController.Interceptor {
|
||||
private val backgroundHandler: Handler,
|
||||
@EpoxyControllerModelHandler
|
||||
private val modelBuilderHandler: Handler
|
||||
) : EpoxyController(modelBuilderHandler, backgroundHandler), Timeline.Listener, EpoxyController.Interceptor {
|
||||
|
||||
interface Callback : BaseCallback, ReactionPillCallback, AvatarCallback, UrlClickCallback, ReadReceiptsCallback {
|
||||
fun onLoadMore(direction: Timeline.Direction)
|
||||
|
@@ -21,3 +21,11 @@ import javax.inject.Qualifier
|
||||
@Qualifier
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class TimelineEventControllerHandler
|
||||
|
||||
@Qualifier
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class EpoxyControllerModelHandler
|
||||
|
||||
@Qualifier
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class EpoxyControllerDiffHandler
|
||||
|
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.home.room.detail.timeline.helper
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.HandlerThread
|
||||
|
||||
object EpoxyHandlerHelper {
|
||||
|
||||
val modelBuildingHandler: Handler
|
||||
|
||||
val diffingHandler: Handler
|
||||
|
||||
init {
|
||||
val handlerThread = HandlerThread("EpoxyControllerModelHandler")
|
||||
handlerThread.start()
|
||||
modelBuildingHandler = Handler(handlerThread.looper)
|
||||
|
||||
val diffHandlerThread = HandlerThread("EpoxyControllerDiffHandler")
|
||||
diffHandlerThread.start()
|
||||
diffingHandler = Handler(diffHandlerThread.looper)
|
||||
}
|
||||
}
|
@@ -17,9 +17,11 @@
|
||||
package im.vector.app.features.home.room.list
|
||||
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import androidx.core.view.isVisible
|
||||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
import com.airbnb.epoxy.EpoxyModelClass
|
||||
import im.vector.app.R
|
||||
@@ -32,8 +34,11 @@ abstract class RoomCategoryItem : VectorEpoxyModel<RoomCategoryItem.Holder>() {
|
||||
|
||||
@EpoxyAttribute lateinit var title: CharSequence
|
||||
@EpoxyAttribute var expanded: Boolean = false
|
||||
@EpoxyAttribute var mode: RoomListViewState.CategoryMode = RoomListViewState.CategoryMode.List
|
||||
@EpoxyAttribute var unreadNotificationCount: Int = 0
|
||||
@EpoxyAttribute var showHighlighted: Boolean = false
|
||||
@EpoxyAttribute var showSwitchMode: Boolean = true
|
||||
@EpoxyAttribute var changeModeListener: ((RoomListViewState.CategoryMode) -> Unit)? = null
|
||||
@EpoxyAttribute var listener: (() -> Unit)? = null
|
||||
|
||||
override fun bind(holder: Holder) {
|
||||
@@ -47,11 +52,32 @@ abstract class RoomCategoryItem : VectorEpoxyModel<RoomCategoryItem.Holder>() {
|
||||
holder.titleView.setCompoundDrawablesWithIntrinsicBounds(null, null, expandedArrowDrawable, null)
|
||||
holder.titleView.text = title
|
||||
holder.rootView.setOnClickListener { listener?.invoke() }
|
||||
|
||||
if (showSwitchMode && expanded) {
|
||||
holder.modeSwitch.isVisible = true
|
||||
holder.modeSwitch.setImageResource(
|
||||
when (mode) {
|
||||
RoomListViewState.CategoryMode.Grid -> R.drawable.ic_mode_grid_24dp
|
||||
RoomListViewState.CategoryMode.List -> R.drawable.ic_mode_list_24dp
|
||||
}
|
||||
)
|
||||
holder.modeSwitch.setOnClickListener {
|
||||
changeModeListener?.invoke(
|
||||
when (mode) {
|
||||
RoomListViewState.CategoryMode.Grid -> RoomListViewState.CategoryMode.List
|
||||
RoomListViewState.CategoryMode.List -> RoomListViewState.CategoryMode.Grid
|
||||
}
|
||||
)
|
||||
}
|
||||
} else {
|
||||
holder.modeSwitch.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
class Holder : VectorEpoxyHolder() {
|
||||
val unreadCounterBadgeView by bind<UnreadCounterBadgeView>(R.id.roomCategoryUnreadCounterBadgeView)
|
||||
val titleView by bind<TextView>(R.id.roomCategoryTitleView)
|
||||
val modeSwitch by bind<ImageView>(R.id.roomCategoryMode)
|
||||
val rootView by bind<ViewGroup>(R.id.roomCategoryRootView)
|
||||
}
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ import org.matrix.android.sdk.api.session.room.notification.RoomNotificationStat
|
||||
sealed class RoomListAction : VectorViewModelAction {
|
||||
data class SelectRoom(val roomSummary: RoomSummary) : RoomListAction()
|
||||
data class ToggleCategory(val category: RoomCategory) : RoomListAction()
|
||||
data class ChangeCategoryMode(val category: RoomCategory, val newCategoryMode: RoomListViewState.CategoryMode) : RoomListAction()
|
||||
data class AcceptInvitation(val roomSummary: RoomSummary) : RoomListAction()
|
||||
data class RejectInvitation(val roomSummary: RoomSummary) : RoomListAction()
|
||||
data class FilterWith(val filter: String) : RoomListAction()
|
||||
|
@@ -17,9 +17,10 @@
|
||||
package im.vector.app.features.home.room.list
|
||||
|
||||
import im.vector.app.features.home.RoomListDisplayMode
|
||||
import io.reactivex.functions.Predicate
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import io.reactivex.functions.Predicate
|
||||
import org.matrix.android.sdk.api.session.room.model.tag.RoomTag
|
||||
|
||||
class RoomListDisplayModeFilter(private val displayMode: RoomListDisplayMode) : Predicate<RoomSummary> {
|
||||
|
||||
@@ -30,9 +31,13 @@ class RoomListDisplayModeFilter(private val displayMode: RoomListDisplayMode) :
|
||||
return when (displayMode) {
|
||||
RoomListDisplayMode.NOTIFICATIONS ->
|
||||
roomSummary.notificationCount > 0 || roomSummary.membership == Membership.INVITE || roomSummary.userDrafts.isNotEmpty()
|
||||
RoomListDisplayMode.PEOPLE -> roomSummary.isDirect && roomSummary.membership.isActive()
|
||||
RoomListDisplayMode.ROOMS -> !roomSummary.isDirect && roomSummary.membership.isActive()
|
||||
RoomListDisplayMode.FILTERED -> roomSummary.membership == Membership.JOIN
|
||||
RoomListDisplayMode.PEOPLE -> roomSummary.isDirect && roomSummary.membership == Membership.JOIN
|
||||
RoomListDisplayMode.ROOMS -> !roomSummary.isDirect && roomSummary.membership == Membership.JOIN
|
||||
RoomListDisplayMode.FILTERED -> roomSummary.membership == Membership.JOIN
|
||||
RoomListDisplayMode.ALL -> roomSummary.membership.isActive()
|
||||
RoomListDisplayMode.FAVORITES -> roomSummary.membership == Membership.JOIN && roomSummary.tags.any { it.name == RoomTag.ROOM_TAG_FAVOURITE }
|
||||
RoomListDisplayMode.LOW_PRIORITY -> roomSummary.membership == Membership.JOIN && roomSummary.tags.any { it.name == RoomTag.ROOM_TAG_LOW_PRIORITY }
|
||||
RoomListDisplayMode.INVITES -> roomSummary.membership == Membership.INVITE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -18,13 +18,14 @@ package im.vector.app.features.home.room.list
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.airbnb.epoxy.OnModelBuildFinishedListener
|
||||
import com.airbnb.mvrx.Fail
|
||||
@@ -37,22 +38,21 @@ import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.LayoutManagerStateRestorer
|
||||
import im.vector.app.core.extensions.cleanup
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.OnBackPressed
|
||||
import im.vector.app.core.platform.StateView
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.core.utils.DimensionConverter
|
||||
import im.vector.app.features.home.RoomListDisplayMode
|
||||
import im.vector.app.features.home.room.list.actions.RoomListActionsArgs
|
||||
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsBottomSheet
|
||||
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedAction
|
||||
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel
|
||||
import im.vector.app.features.home.room.list.widget.FabMenuView
|
||||
import im.vector.app.features.notifications.NotificationDrawerManager
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.android.synthetic.main.fragment_room_list.*
|
||||
import org.matrix.android.sdk.api.failure.Failure
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.android.synthetic.main.fragment_room_list.*
|
||||
import javax.inject.Inject
|
||||
|
||||
@Parcelize
|
||||
@@ -64,9 +64,9 @@ class RoomListFragment @Inject constructor(
|
||||
private val roomController: RoomSummaryController,
|
||||
val roomListViewModelFactory: RoomListViewModel.Factory,
|
||||
private val notificationDrawerManager: NotificationDrawerManager,
|
||||
private val sharedViewPool: RecyclerView.RecycledViewPool
|
||||
|
||||
) : VectorBaseFragment(), RoomSummaryController.Listener, OnBackPressed, FabMenuView.Listener {
|
||||
private val sharedViewPool: RecyclerView.RecycledViewPool,
|
||||
private val dimensionConverter: DimensionConverter
|
||||
) : VectorBaseFragment(), RoomSummaryController.Listener {
|
||||
|
||||
private var modelBuildListener: OnModelBuildFinishedListener? = null
|
||||
private lateinit var sharedActionViewModel: RoomListQuickActionsSharedActionViewModel
|
||||
@@ -98,20 +98,16 @@ class RoomListFragment @Inject constructor(
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setupCreateRoomButton()
|
||||
setupRecyclerView()
|
||||
sharedActionViewModel = activityViewModelProvider.get(RoomListQuickActionsSharedActionViewModel::class.java)
|
||||
roomListViewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is RoomListViewEvents.Loading -> showLoading(it.message)
|
||||
is RoomListViewEvents.Failure -> showFailure(it.throwable)
|
||||
is RoomListViewEvents.Loading -> showLoading(it.message)
|
||||
is RoomListViewEvents.Failure -> showFailure(it.throwable)
|
||||
is RoomListViewEvents.SelectRoom -> handleSelectRoom(it)
|
||||
is RoomListViewEvents.Done -> Unit
|
||||
is RoomListViewEvents.Done -> Unit
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
createChatFabMenu.listener = this
|
||||
|
||||
sharedActionViewModel
|
||||
.observe()
|
||||
.subscribe { handleQuickActions(it) }
|
||||
@@ -128,7 +124,6 @@ class RoomListFragment @Inject constructor(
|
||||
roomListView.cleanup()
|
||||
roomController.listener = null
|
||||
stateRestorer.clear()
|
||||
createChatFabMenu.listener = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
@@ -136,44 +131,44 @@ class RoomListFragment @Inject constructor(
|
||||
navigator.openRoom(requireActivity(), event.roomSummary.roomId)
|
||||
}
|
||||
|
||||
private fun setupCreateRoomButton() {
|
||||
when (roomListParams.displayMode) {
|
||||
RoomListDisplayMode.NOTIFICATIONS -> createChatFabMenu.isVisible = true
|
||||
RoomListDisplayMode.PEOPLE -> createChatRoomButton.isVisible = true
|
||||
RoomListDisplayMode.ROOMS -> createGroupRoomButton.isVisible = true
|
||||
else -> Unit // No button in this mode
|
||||
}
|
||||
|
||||
createChatRoomButton.debouncedClicks {
|
||||
createDirectChat()
|
||||
}
|
||||
createGroupRoomButton.debouncedClicks {
|
||||
openRoomDirectory()
|
||||
}
|
||||
|
||||
// Hide FAB when list is scrolling
|
||||
roomListView.addOnScrollListener(
|
||||
object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
createChatFabMenu.removeCallbacks(showFabRunnable)
|
||||
|
||||
when (newState) {
|
||||
RecyclerView.SCROLL_STATE_IDLE -> {
|
||||
createChatFabMenu.postDelayed(showFabRunnable, 250)
|
||||
}
|
||||
RecyclerView.SCROLL_STATE_DRAGGING,
|
||||
RecyclerView.SCROLL_STATE_SETTLING -> {
|
||||
when (roomListParams.displayMode) {
|
||||
RoomListDisplayMode.NOTIFICATIONS -> createChatFabMenu.hide()
|
||||
RoomListDisplayMode.PEOPLE -> createChatRoomButton.hide()
|
||||
RoomListDisplayMode.ROOMS -> createGroupRoomButton.hide()
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// private fun setupCreateRoomButton() {
|
||||
// when (roomListParams.displayMode) {
|
||||
// RoomListDisplayMode.NOTIFICATIONS -> createChatFabMenu.isVisible = true
|
||||
// RoomListDisplayMode.PEOPLE -> createChatRoomButton.isVisible = true
|
||||
// RoomListDisplayMode.ROOMS -> createGroupRoomButton.isVisible = true
|
||||
// else -> Unit // No button in this mode
|
||||
// }
|
||||
//
|
||||
// createChatRoomButton.debouncedClicks {
|
||||
// createDirectChat()
|
||||
// }
|
||||
// createGroupRoomButton.debouncedClicks {
|
||||
// openRoomDirectory()
|
||||
// }
|
||||
//
|
||||
// // Hide FAB when list is scrolling
|
||||
// roomListView.addOnScrollListener(
|
||||
// object : RecyclerView.OnScrollListener() {
|
||||
// override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
// createChatFabMenu.removeCallbacks(showFabRunnable)
|
||||
//
|
||||
// when (newState) {
|
||||
// RecyclerView.SCROLL_STATE_IDLE -> {
|
||||
// createChatFabMenu.postDelayed(showFabRunnable, 250)
|
||||
// }
|
||||
// RecyclerView.SCROLL_STATE_DRAGGING,
|
||||
// RecyclerView.SCROLL_STATE_SETTLING -> {
|
||||
// when (roomListParams.displayMode) {
|
||||
// RoomListDisplayMode.NOTIFICATIONS -> createChatFabMenu.hide()
|
||||
// RoomListDisplayMode.PEOPLE -> createChatRoomButton.hide()
|
||||
// RoomListDisplayMode.ROOMS -> createGroupRoomButton.hide()
|
||||
// else -> Unit
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
fun filterRoomsWith(filter: String) {
|
||||
// Scroll the list to top
|
||||
@@ -182,16 +177,9 @@ class RoomListFragment @Inject constructor(
|
||||
roomListViewModel.handle(RoomListAction.FilterWith(filter))
|
||||
}
|
||||
|
||||
override fun openRoomDirectory(initialFilter: String) {
|
||||
navigator.openRoomDirectory(requireActivity(), initialFilter)
|
||||
}
|
||||
|
||||
override fun createDirectChat() {
|
||||
navigator.openCreateDirectRoom(requireActivity())
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
val layoutManager = LinearLayoutManager(context)
|
||||
val numOfColumns = getNumberOfColumns()
|
||||
val layoutManager = GridLayoutManager(context, numOfColumns)
|
||||
stateRestorer = LayoutManagerStateRestorer(layoutManager).register()
|
||||
roomListView.layoutManager = layoutManager
|
||||
roomListView.itemAnimator = RoomListAnimator()
|
||||
@@ -202,40 +190,49 @@ class RoomListFragment @Inject constructor(
|
||||
roomController.addModelBuildListener(modelBuildListener)
|
||||
roomListView.adapter = roomController.adapter
|
||||
stateView.contentView = roomListView
|
||||
|
||||
roomController.spanCount = numOfColumns
|
||||
layoutManager.spanSizeLookup = roomController.spanSizeLookup
|
||||
}
|
||||
|
||||
private val showFabRunnable = Runnable {
|
||||
if (isAdded) {
|
||||
when (roomListParams.displayMode) {
|
||||
RoomListDisplayMode.NOTIFICATIONS -> createChatFabMenu.show()
|
||||
RoomListDisplayMode.PEOPLE -> createChatRoomButton.show()
|
||||
RoomListDisplayMode.ROOMS -> createGroupRoomButton.show()
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
private fun getNumberOfColumns(): Int {
|
||||
val displayMetrics = DisplayMetrics()
|
||||
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
|
||||
return dimensionConverter.pxToDp(displayMetrics.widthPixels) / ITEM_SIZE_DP
|
||||
}
|
||||
|
||||
// private val showFabRunnable = Runnable {
|
||||
// if (isAdded) {
|
||||
// when (roomListParams.displayMode) {
|
||||
// RoomListDisplayMode.NOTIFICATIONS -> createChatFabMenu.show()
|
||||
// RoomListDisplayMode.PEOPLE -> createChatRoomButton.show()
|
||||
// RoomListDisplayMode.ROOMS -> createGroupRoomButton.show()
|
||||
// else -> Unit
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
private fun handleQuickActions(quickAction: RoomListQuickActionsSharedAction) {
|
||||
when (quickAction) {
|
||||
is RoomListQuickActionsSharedAction.NotificationsAllNoisy -> {
|
||||
is RoomListQuickActionsSharedAction.NotificationsAllNoisy -> {
|
||||
roomListViewModel.handle(RoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.ALL_MESSAGES_NOISY))
|
||||
}
|
||||
is RoomListQuickActionsSharedAction.NotificationsAll -> {
|
||||
is RoomListQuickActionsSharedAction.NotificationsAll -> {
|
||||
roomListViewModel.handle(RoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.ALL_MESSAGES))
|
||||
}
|
||||
is RoomListQuickActionsSharedAction.NotificationsMentionsOnly -> {
|
||||
roomListViewModel.handle(RoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.MENTIONS_ONLY))
|
||||
}
|
||||
is RoomListQuickActionsSharedAction.NotificationsMute -> {
|
||||
is RoomListQuickActionsSharedAction.NotificationsMute -> {
|
||||
roomListViewModel.handle(RoomListAction.ChangeRoomNotificationState(quickAction.roomId, RoomNotificationState.MUTE))
|
||||
}
|
||||
is RoomListQuickActionsSharedAction.Settings -> {
|
||||
is RoomListQuickActionsSharedAction.Settings -> {
|
||||
navigator.openRoomProfile(requireActivity(), quickAction.roomId)
|
||||
}
|
||||
is RoomListQuickActionsSharedAction.Favorite -> {
|
||||
is RoomListQuickActionsSharedAction.Favorite -> {
|
||||
roomListViewModel.handle(RoomListAction.ToggleFavorite(quickAction.roomId))
|
||||
}
|
||||
is RoomListQuickActionsSharedAction.Leave -> {
|
||||
is RoomListQuickActionsSharedAction.Leave -> {
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setTitle(R.string.room_participants_leave_prompt_title)
|
||||
.setMessage(R.string.room_participants_leave_prompt_msg)
|
||||
@@ -252,12 +249,16 @@ class RoomListFragment @Inject constructor(
|
||||
override fun invalidate() = withState(roomListViewModel) { state ->
|
||||
when (state.asyncFilteredRooms) {
|
||||
is Incomplete -> renderLoading()
|
||||
is Success -> renderSuccess(state)
|
||||
is Fail -> renderFailure(state.asyncFilteredRooms.error)
|
||||
is Success -> renderSuccess(state)
|
||||
is Fail -> renderFailure(state.asyncFilteredRooms.error)
|
||||
}
|
||||
roomController.update(state)
|
||||
// Mark all as read menu
|
||||
when (roomListParams.displayMode) {
|
||||
RoomListDisplayMode.ALL,
|
||||
RoomListDisplayMode.FAVORITES,
|
||||
RoomListDisplayMode.LOW_PRIORITY,
|
||||
RoomListDisplayMode.INVITES,
|
||||
RoomListDisplayMode.NOTIFICATIONS,
|
||||
RoomListDisplayMode.PEOPLE,
|
||||
RoomListDisplayMode.ROOMS -> {
|
||||
@@ -302,19 +303,19 @@ class RoomListFragment @Inject constructor(
|
||||
getString(R.string.room_list_catchup_empty_body))
|
||||
}
|
||||
}
|
||||
RoomListDisplayMode.PEOPLE ->
|
||||
RoomListDisplayMode.PEOPLE ->
|
||||
StateView.State.Empty(
|
||||
getString(R.string.room_list_people_empty_title),
|
||||
ContextCompat.getDrawable(requireContext(), R.drawable.ic_home_bottom_chat),
|
||||
getString(R.string.room_list_people_empty_body)
|
||||
)
|
||||
RoomListDisplayMode.ROOMS ->
|
||||
RoomListDisplayMode.ROOMS ->
|
||||
StateView.State.Empty(
|
||||
getString(R.string.room_list_rooms_empty_title),
|
||||
ContextCompat.getDrawable(requireContext(), R.drawable.ic_home_bottom_group),
|
||||
getString(R.string.room_list_rooms_empty_body)
|
||||
)
|
||||
else ->
|
||||
else ->
|
||||
// Always display the content in this mode, because if the footer
|
||||
StateView.State.Content
|
||||
}
|
||||
@@ -333,13 +334,6 @@ class RoomListFragment @Inject constructor(
|
||||
stateView.state = StateView.State.Error(message)
|
||||
}
|
||||
|
||||
override fun onBackPressed(toolbarButton: Boolean): Boolean {
|
||||
if (createChatFabMenu.onBackPressed()) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// RoomSummaryController.Callback **************************************************************
|
||||
|
||||
override fun onRoomClicked(room: RoomSummary) {
|
||||
@@ -368,7 +362,23 @@ class RoomListFragment @Inject constructor(
|
||||
roomListViewModel.handle(RoomListAction.ToggleCategory(roomCategory))
|
||||
}
|
||||
|
||||
override fun onChangeModeRoomCategory(roomCategory: RoomCategory, newMode: RoomListViewState.CategoryMode) {
|
||||
roomListViewModel.handle(RoomListAction.ChangeCategoryMode(roomCategory, newMode))
|
||||
}
|
||||
|
||||
override fun createRoom(initialName: String) {
|
||||
navigator.openCreateRoom(requireActivity(), initialName)
|
||||
}
|
||||
|
||||
override fun createDirectChat() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun openRoomDirectory(initialFilter: String) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ITEM_SIZE_DP = 80
|
||||
}
|
||||
}
|
||||
|
@@ -22,6 +22,9 @@ import com.airbnb.mvrx.ViewModelContext
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.core.utils.DataSource
|
||||
import im.vector.app.features.home.RoomListDisplayMode
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.NoOpMatrixCallback
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
@@ -29,14 +32,14 @@ import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.session.room.model.tag.RoomTag
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import org.matrix.android.sdk.rx.rx
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class RoomListViewModel @Inject constructor(initialState: RoomListViewState,
|
||||
private val session: Session,
|
||||
private val roomSummariesSource: DataSource<List<RoomSummary>>)
|
||||
private val roomSummariesSource: DataSource<List<RoomSummary>>,
|
||||
private val vectorPreferences: VectorPreferences)
|
||||
: VectorViewModel<RoomListViewState, RoomListAction, RoomListViewEvents>(initialState) {
|
||||
|
||||
interface Factory {
|
||||
@@ -64,6 +67,7 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState,
|
||||
when (action) {
|
||||
is RoomListAction.SelectRoom -> handleSelectRoom(action)
|
||||
is RoomListAction.ToggleCategory -> handleToggleCategory(action)
|
||||
is RoomListAction.ChangeCategoryMode -> handleChangeCategoryMode(action)
|
||||
is RoomListAction.AcceptInvitation -> handleAcceptInvitation(action)
|
||||
is RoomListAction.RejectInvitation -> handleRejectInvitation(action)
|
||||
is RoomListAction.FilterWith -> handleFilter(action)
|
||||
@@ -84,6 +88,10 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState,
|
||||
this.toggle(action.category)
|
||||
}
|
||||
|
||||
private fun handleChangeCategoryMode(action: RoomListAction.ChangeCategoryMode) = setState {
|
||||
this.setMode(action.category, action.newCategoryMode)
|
||||
}
|
||||
|
||||
private fun handleFilter(action: RoomListAction.FilterWith) {
|
||||
setState {
|
||||
copy(
|
||||
@@ -212,34 +220,75 @@ class RoomListViewModel @Inject constructor(initialState: RoomListViewState,
|
||||
}
|
||||
|
||||
private fun buildRoomSummaries(rooms: List<RoomSummary>): RoomSummaries {
|
||||
// Set up init size on directChats and groupRooms as they are the biggest ones
|
||||
val invites = ArrayList<RoomSummary>()
|
||||
val favourites = ArrayList<RoomSummary>()
|
||||
val others = ArrayList<RoomSummary>(rooms.size)
|
||||
val favorite = ArrayList<RoomSummary>()
|
||||
val directChats = ArrayList<RoomSummary>(rooms.size)
|
||||
val groupRooms = ArrayList<RoomSummary>(rooms.size)
|
||||
val lowPriorities = ArrayList<RoomSummary>()
|
||||
val serverNotices = ArrayList<RoomSummary>()
|
||||
|
||||
rooms
|
||||
.filter { roomListDisplayModeFilter.test(it) }
|
||||
.forEach { room ->
|
||||
val tags = room.tags.map { it.name }
|
||||
when {
|
||||
room.membership == Membership.INVITE -> invites.add(room)
|
||||
tags.contains(RoomTag.ROOM_TAG_SERVER_NOTICE) -> serverNotices.add(room)
|
||||
tags.contains(RoomTag.ROOM_TAG_FAVOURITE) -> favourites.add(room)
|
||||
tags.contains(RoomTag.ROOM_TAG_LOW_PRIORITY) -> lowPriorities.add(room)
|
||||
room.isDirect -> directChats.add(room)
|
||||
else -> groupRooms.add(room)
|
||||
if (vectorPreferences.labUseTabNavigation()) {
|
||||
rooms
|
||||
.filter { roomListDisplayModeFilter.test(it) }
|
||||
.forEach { room ->
|
||||
if (room.membership == Membership.INVITE) {
|
||||
invites.add(room)
|
||||
} else {
|
||||
val tags = room.tags.map { it.name }
|
||||
if (vectorPreferences.labPinFavInTabNavigation() && tags.contains(RoomTag.ROOM_TAG_FAVOURITE)) {
|
||||
favorite.add(room)
|
||||
} else others.add(room)
|
||||
}
|
||||
}
|
||||
return RoomSummaries().apply {
|
||||
if (vectorPreferences.labPinFavInTabNavigation()) {
|
||||
put(RoomCategory.FAVOURITE, favorite)
|
||||
}
|
||||
return RoomSummaries().apply {
|
||||
put(RoomCategory.INVITE, invites)
|
||||
put(RoomCategory.FAVOURITE, favourites)
|
||||
put(RoomCategory.DIRECT, directChats)
|
||||
put(RoomCategory.GROUP, groupRooms)
|
||||
put(RoomCategory.LOW_PRIORITY, lowPriorities)
|
||||
put(RoomCategory.SERVER_NOTICE, serverNotices)
|
||||
put(RoomCategory.INVITE, invites)
|
||||
put(RoomCategory.CHATS, others)
|
||||
}
|
||||
} else {
|
||||
rooms
|
||||
.filter { roomListDisplayModeFilter.test(it) }
|
||||
.forEach { room ->
|
||||
val tags = room.tags.map { it.name }
|
||||
|
||||
if (displayMode == RoomListDisplayMode.ALL) {
|
||||
if (room.membership == Membership.INVITE) {
|
||||
invites.add(room)
|
||||
} else {
|
||||
if (vectorPreferences.labPinFavInTabNavigation() && tags.contains(RoomTag.ROOM_TAG_FAVOURITE)) {
|
||||
favorite.add(room)
|
||||
} else others.add(room)
|
||||
}
|
||||
} else {
|
||||
when {
|
||||
room.membership == Membership.INVITE -> invites.add(room)
|
||||
tags.contains(RoomTag.ROOM_TAG_SERVER_NOTICE) -> serverNotices.add(room)
|
||||
tags.contains(RoomTag.ROOM_TAG_FAVOURITE) -> favorite.add(room)
|
||||
tags.contains(RoomTag.ROOM_TAG_LOW_PRIORITY) -> lowPriorities.add(room)
|
||||
room.isDirect -> directChats.add(room)
|
||||
else -> groupRooms.add(room)
|
||||
}
|
||||
}
|
||||
}
|
||||
return RoomSummaries().apply {
|
||||
put(RoomCategory.INVITE, invites)
|
||||
|
||||
if (displayMode == RoomListDisplayMode.ALL) {
|
||||
if (vectorPreferences.labPinFavInTabNavigation()) {
|
||||
put(RoomCategory.FAVOURITE, favorite)
|
||||
}
|
||||
put(RoomCategory.CHATS, others)
|
||||
} else {
|
||||
put(RoomCategory.FAVOURITE, favorite)
|
||||
put(RoomCategory.DIRECT, directChats)
|
||||
put(RoomCategory.GROUP, groupRooms)
|
||||
put(RoomCategory.LOW_PRIORITY, lowPriorities)
|
||||
put(RoomCategory.SERVER_NOTICE, serverNotices)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -17,19 +17,22 @@
|
||||
package im.vector.app.features.home.room.list
|
||||
|
||||
import im.vector.app.features.home.HomeRoomListDataSource
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Provider
|
||||
|
||||
class RoomListViewModelFactory @Inject constructor(private val session: Provider<Session>,
|
||||
private val homeRoomListDataSource: Provider<HomeRoomListDataSource>)
|
||||
private val homeRoomListDataSource: Provider<HomeRoomListDataSource>,
|
||||
private val vectorPreferences: VectorPreferences)
|
||||
: RoomListViewModel.Factory {
|
||||
|
||||
override fun create(initialState: RoomListViewState): RoomListViewModel {
|
||||
return RoomListViewModel(
|
||||
initialState,
|
||||
session.get(),
|
||||
homeRoomListDataSource.get()
|
||||
homeRoomListDataSource.get(),
|
||||
vectorPreferences
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -37,7 +37,14 @@ data class RoomListViewState(
|
||||
val isDirectRoomsExpanded: Boolean = true,
|
||||
val isGroupRoomsExpanded: Boolean = true,
|
||||
val isLowPriorityRoomsExpanded: Boolean = true,
|
||||
val isServerNoticeRoomsExpanded: Boolean = true
|
||||
val isServerNoticeRoomsExpanded: Boolean = true,
|
||||
val isChatRoomsExpanded: Boolean = true,
|
||||
val favouriteRoomsMode: CategoryMode = CategoryMode.Grid,
|
||||
val directRoomsMode: CategoryMode = CategoryMode.List,
|
||||
val groupRoomsMode: CategoryMode = CategoryMode.List,
|
||||
val lowPriorityRoomsMode: CategoryMode = CategoryMode.List,
|
||||
val serverNoticeRoomsMode: CategoryMode = CategoryMode.List,
|
||||
val chatsRoomsMode: CategoryMode = CategoryMode.List
|
||||
) : MvRxState {
|
||||
|
||||
constructor(args: RoomListParams) : this(displayMode = args.displayMode)
|
||||
@@ -50,6 +57,26 @@ data class RoomListViewState(
|
||||
RoomCategory.GROUP -> isGroupRoomsExpanded
|
||||
RoomCategory.LOW_PRIORITY -> isLowPriorityRoomsExpanded
|
||||
RoomCategory.SERVER_NOTICE -> isServerNoticeRoomsExpanded
|
||||
// else -> true
|
||||
RoomCategory.CHATS -> isChatRoomsExpanded
|
||||
}
|
||||
}
|
||||
|
||||
enum class CategoryMode {
|
||||
List,
|
||||
Grid
|
||||
}
|
||||
|
||||
fun getCategoryMode(roomCategory: RoomCategory): CategoryMode {
|
||||
return when (roomCategory) {
|
||||
RoomCategory.INVITE -> CategoryMode.List
|
||||
RoomCategory.FAVOURITE -> CategoryMode.Grid
|
||||
RoomCategory.DIRECT -> directRoomsMode
|
||||
RoomCategory.GROUP -> groupRoomsMode
|
||||
RoomCategory.LOW_PRIORITY -> lowPriorityRoomsMode
|
||||
RoomCategory.SERVER_NOTICE -> serverNoticeRoomsMode
|
||||
RoomCategory.CHATS -> chatsRoomsMode
|
||||
// else -> CategoryMode.List
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +88,19 @@ data class RoomListViewState(
|
||||
RoomCategory.GROUP -> copy(isGroupRoomsExpanded = !isGroupRoomsExpanded)
|
||||
RoomCategory.LOW_PRIORITY -> copy(isLowPriorityRoomsExpanded = !isLowPriorityRoomsExpanded)
|
||||
RoomCategory.SERVER_NOTICE -> copy(isServerNoticeRoomsExpanded = !isServerNoticeRoomsExpanded)
|
||||
RoomCategory.CHATS -> copy(isChatRoomsExpanded = !isChatRoomsExpanded)
|
||||
}
|
||||
}
|
||||
|
||||
fun setMode(roomCategory: RoomCategory, newCategoryMode: CategoryMode): RoomListViewState {
|
||||
return when (roomCategory) {
|
||||
RoomCategory.INVITE -> this
|
||||
RoomCategory.FAVOURITE -> copy(favouriteRoomsMode = newCategoryMode)
|
||||
RoomCategory.DIRECT -> copy(directRoomsMode = newCategoryMode)
|
||||
RoomCategory.GROUP -> copy(groupRoomsMode = newCategoryMode)
|
||||
RoomCategory.LOW_PRIORITY -> copy(lowPriorityRoomsMode = newCategoryMode)
|
||||
RoomCategory.SERVER_NOTICE -> copy(serverNoticeRoomsMode = newCategoryMode)
|
||||
RoomCategory.CHATS -> copy(chatsRoomsMode = newCategoryMode)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +116,7 @@ typealias RoomSummaries = LinkedHashMap<RoomCategory, List<RoomSummary>>
|
||||
|
||||
enum class RoomCategory(@StringRes val titleRes: Int) {
|
||||
INVITE(R.string.invitations_header),
|
||||
CHATS(R.string.room_list_tabs_all),
|
||||
FAVOURITE(R.string.bottom_action_favourites),
|
||||
DIRECT(R.string.bottom_action_people_x),
|
||||
GROUP(R.string.bottom_action_rooms),
|
||||
|
@@ -16,25 +16,44 @@
|
||||
|
||||
package im.vector.app.features.home.room.list
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import android.os.Handler
|
||||
import android.view.View
|
||||
import com.airbnb.epoxy.EpoxyController
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.helpFooterItem
|
||||
import im.vector.app.core.resources.ColorProvider
|
||||
import im.vector.app.core.resources.DrawableProvider
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.core.resources.UserPreferencesProvider
|
||||
import im.vector.app.core.ui.list.genericFooterItem
|
||||
import im.vector.app.core.utils.DebouncedClickListener
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.home.RoomListDisplayMode
|
||||
import im.vector.app.features.home.room.detail.timeline.EpoxyControllerDiffHandler
|
||||
import im.vector.app.features.home.room.detail.timeline.EpoxyControllerModelHandler
|
||||
import im.vector.app.features.home.room.filtered.FilteredRoomFooterItem
|
||||
import im.vector.app.features.home.room.filtered.filteredRoomFooterItem
|
||||
import im.vector.app.features.home.room.list.grid.roomGridItem
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||
import javax.inject.Inject
|
||||
|
||||
class RoomSummaryController @Inject constructor(private val stringProvider: StringProvider,
|
||||
private val roomSummaryItemFactory: RoomSummaryItemFactory,
|
||||
private val roomListNameFilter: RoomListNameFilter,
|
||||
private val userPreferencesProvider: UserPreferencesProvider
|
||||
) : EpoxyController() {
|
||||
private val userPreferencesProvider: UserPreferencesProvider,
|
||||
private val avatarRenderer: AvatarRenderer,
|
||||
private val vectorPreferences: VectorPreferences,
|
||||
private val drawableProvider: DrawableProvider,
|
||||
private val colorProvider: ColorProvider,
|
||||
@EpoxyControllerModelHandler
|
||||
private val backgroundModelHandler: Handler,
|
||||
@EpoxyControllerDiffHandler
|
||||
private val backgroundDiffHandler: Handler
|
||||
) : EpoxyController(backgroundModelHandler, backgroundDiffHandler) {
|
||||
|
||||
var listener: Listener? = null
|
||||
|
||||
@@ -73,6 +92,7 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri
|
||||
.filter { it.membership == Membership.JOIN && roomListNameFilter.test(it) }
|
||||
|
||||
buildRoomModels(filteredSummaries,
|
||||
RoomListViewState.CategoryMode.List,
|
||||
viewState.roomMembershipChanges,
|
||||
emptySet())
|
||||
|
||||
@@ -82,22 +102,53 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri
|
||||
private fun buildRooms(viewState: RoomListViewState) {
|
||||
var showHelp = false
|
||||
val roomSummaries = viewState.asyncFilteredRooms()
|
||||
if (vectorPreferences.labUseTabNavigation() && vectorPreferences.labPinFavInTabNavigation()
|
||||
&& !roomSummaries?.get(RoomCategory.FAVOURITE).isNullOrEmpty()) {
|
||||
genericFooterItem {
|
||||
id("Top Spacing")
|
||||
text(" ")
|
||||
spanSizeOverride { _, _, _ -> spanCount }
|
||||
}
|
||||
}
|
||||
roomSummaries?.forEach { (category, summaries) ->
|
||||
if (summaries.isEmpty()) {
|
||||
return@forEach
|
||||
} else {
|
||||
val isExpanded = viewState.isCategoryExpanded(category)
|
||||
buildRoomCategory(viewState, summaries, category.titleRes, viewState.isCategoryExpanded(category)) {
|
||||
listener?.onToggleRoomCategory(category)
|
||||
}
|
||||
if (isExpanded) {
|
||||
val mode = viewState.getCategoryMode(category)
|
||||
if (vectorPreferences.labUseTabNavigation()) {
|
||||
buildRoomModels(summaries,
|
||||
mode,
|
||||
viewState.roomMembershipChanges,
|
||||
emptySet())
|
||||
// Never set showHelp to true for invitation
|
||||
if (category != RoomCategory.INVITE) {
|
||||
showHelp = userPreferencesProvider.shouldShowLongClickOnRoomHelp()
|
||||
}
|
||||
} else {
|
||||
buildRoomCategory(
|
||||
viewState,
|
||||
category,
|
||||
summaries,
|
||||
isExpanded,
|
||||
mode,
|
||||
{ newMode ->
|
||||
listener?.onChangeModeRoomCategory(category, newMode)
|
||||
},
|
||||
{
|
||||
listener?.onToggleRoomCategory(category)
|
||||
}
|
||||
)
|
||||
if (isExpanded) {
|
||||
buildRoomModels(summaries,
|
||||
mode,
|
||||
viewState.roomMembershipChanges,
|
||||
emptySet())
|
||||
// Never set showHelp to true for invitation
|
||||
if (category != RoomCategory.INVITE) {
|
||||
showHelp = userPreferencesProvider.shouldShowLongClickOnRoomHelp()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,6 +162,7 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri
|
||||
helpFooterItem {
|
||||
id("long_click_help")
|
||||
text(stringProvider.getString(R.string.help_long_click_on_room_for_more_options))
|
||||
spanSizeOverride { _, _, _ -> spanCount }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,13 +171,16 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri
|
||||
id("filter_footer")
|
||||
listener(listener)
|
||||
currentFilter(viewState.roomFilter)
|
||||
spanSizeOverride { _, _, _ -> spanCount }
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildRoomCategory(viewState: RoomListViewState,
|
||||
category: RoomCategory,
|
||||
summaries: List<RoomSummary>,
|
||||
@StringRes titleRes: Int,
|
||||
isExpanded: Boolean,
|
||||
mode: RoomListViewState.CategoryMode,
|
||||
changeModeListener: (RoomListViewState.CategoryMode) -> Unit,
|
||||
mutateExpandedState: () -> Unit) {
|
||||
// TODO should add some business logic later
|
||||
val unreadCount = if (summaries.isEmpty()) {
|
||||
@@ -135,33 +190,73 @@ class RoomSummaryController @Inject constructor(private val stringProvider: Stri
|
||||
}
|
||||
val showHighlighted = summaries.any { it.highlightCount > 0 }
|
||||
roomCategoryItem {
|
||||
id(titleRes)
|
||||
title(stringProvider.getString(titleRes))
|
||||
id(category.titleRes)
|
||||
title(stringProvider.getString(category.titleRes))
|
||||
expanded(isExpanded)
|
||||
unreadNotificationCount(unreadCount)
|
||||
showHighlighted(showHighlighted)
|
||||
showSwitchMode(category != RoomCategory.INVITE)
|
||||
mode(mode)
|
||||
listener {
|
||||
mutateExpandedState()
|
||||
update(viewState)
|
||||
}
|
||||
changeModeListener(changeModeListener)
|
||||
spanSizeOverride { _, _, _ -> spanCount }
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildRoomModels(summaries: List<RoomSummary>,
|
||||
mode: RoomListViewState.CategoryMode,
|
||||
roomChangedMembershipStates: Map<String, ChangeMembershipState>,
|
||||
selectedRoomIds: Set<String>) {
|
||||
summaries.forEach { roomSummary ->
|
||||
roomSummaryItemFactory
|
||||
.create(roomSummary,
|
||||
roomChangedMembershipStates,
|
||||
selectedRoomIds,
|
||||
listener)
|
||||
.addTo(this)
|
||||
when (mode) {
|
||||
RoomListViewState.CategoryMode.List ->
|
||||
summaries.forEach { roomSummary ->
|
||||
roomSummaryItemFactory
|
||||
.create(roomSummary,
|
||||
roomChangedMembershipStates,
|
||||
selectedRoomIds,
|
||||
spanCount,
|
||||
listener)
|
||||
.addTo(this)
|
||||
}
|
||||
RoomListViewState.CategoryMode.Grid -> {
|
||||
// Use breadcrumbs for the moment
|
||||
summaries.forEach { roomSummary ->
|
||||
roomGridItem {
|
||||
id(roomSummary.roomId)
|
||||
hasTypingUsers(roomSummary.typingUsers.isNotEmpty())
|
||||
avatarRenderer(avatarRenderer)
|
||||
matrixItem(roomSummary.toMatrixItem())
|
||||
apply {
|
||||
if (roomSummary.isFavorite) {
|
||||
textDrawableLeft(drawableProvider.getDrawable(R.drawable.ic_star_green_24dp))
|
||||
}
|
||||
}
|
||||
|
||||
unreadNotificationCount(roomSummary.notificationCount)
|
||||
showHighlighted(roomSummary.highlightCount > 0)
|
||||
hasUnreadMessage(roomSummary.hasUnreadMessages)
|
||||
hasDraft(roomSummary.userDrafts.isNotEmpty())
|
||||
itemLongClickListener { _ ->
|
||||
listener?.onRoomLongClicked(roomSummary) ?: false
|
||||
}
|
||||
itemClickListener(
|
||||
DebouncedClickListener(View.OnClickListener { _ ->
|
||||
listener?.onRoomClicked(roomSummary)
|
||||
})
|
||||
)
|
||||
spanCount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface Listener : FilteredRoomFooterItem.FilteredRoomFooterItemListener {
|
||||
fun onToggleRoomCategory(roomCategory: RoomCategory)
|
||||
fun onChangeModeRoomCategory(roomCategory: RoomCategory, newMode: RoomListViewState.CategoryMode)
|
||||
fun onRoomClicked(room: RoomSummary)
|
||||
fun onRoomLongClicked(room: RoomSummary): Boolean
|
||||
fun onRejectRoomInvitation(room: RoomSummary)
|
||||
|
@@ -41,18 +41,25 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor
|
||||
fun create(roomSummary: RoomSummary,
|
||||
roomChangeMembershipStates: Map<String, ChangeMembershipState>,
|
||||
selectedRoomIds: Set<String>,
|
||||
spanCount: Int,
|
||||
listener: RoomSummaryController.Listener?): VectorEpoxyModel<*> {
|
||||
return when (roomSummary.membership) {
|
||||
Membership.INVITE -> {
|
||||
val changeMembershipState = roomChangeMembershipStates[roomSummary.roomId] ?: ChangeMembershipState.Unknown
|
||||
createInvitationItem(roomSummary, changeMembershipState, listener)
|
||||
createInvitationItem(roomSummary, changeMembershipState, spanCount, listener)
|
||||
}
|
||||
else -> createRoomItem(roomSummary, selectedRoomIds, listener?.let { it::onRoomClicked }, listener?.let { it::onRoomLongClicked })
|
||||
else -> createRoomItem(roomSummary,
|
||||
selectedRoomIds,
|
||||
spanCount,
|
||||
listener?.let { it::onRoomClicked },
|
||||
listener?.let { it::onRoomLongClicked }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createInvitationItem(roomSummary: RoomSummary,
|
||||
changeMembershipState: ChangeMembershipState,
|
||||
spanCount: Int,
|
||||
listener: RoomSummaryController.Listener?): VectorEpoxyModel<*> {
|
||||
val secondLine = if (roomSummary.isDirect) {
|
||||
roomSummary.inviterId
|
||||
@@ -71,11 +78,13 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor
|
||||
.acceptListener { listener?.onAcceptRoomInvitation(roomSummary) }
|
||||
.rejectListener { listener?.onRejectRoomInvitation(roomSummary) }
|
||||
.listener { listener?.onRoomClicked(roomSummary) }
|
||||
.spanSizeOverride { _, _, _ -> spanCount }
|
||||
}
|
||||
|
||||
fun createRoomItem(
|
||||
roomSummary: RoomSummary,
|
||||
selectedRoomIds: Set<String>,
|
||||
spanCount: Int,
|
||||
onClick: ((RoomSummary) -> Unit)?,
|
||||
onLongClick: ((RoomSummary) -> Boolean)?
|
||||
): VectorEpoxyModel<*> {
|
||||
@@ -113,5 +122,6 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor
|
||||
onClick?.invoke(roomSummary)
|
||||
})
|
||||
)
|
||||
.spanSizeOverride { _, _, _ -> spanCount }
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.app.features.home.room.list.grid
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.view.HapticFeedbackConstants
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.isVisible
|
||||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
import com.airbnb.epoxy.EpoxyModelClass
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import im.vector.app.features.home.room.list.UnreadCounterBadgeView
|
||||
import org.matrix.android.sdk.api.util.MatrixItem
|
||||
|
||||
@EpoxyModelClass(layout = R.layout.item_room_grid)
|
||||
abstract class RoomGridItem : VectorEpoxyModel<RoomGridItem.Holder>() {
|
||||
|
||||
@EpoxyAttribute var hasTypingUsers: Boolean = false
|
||||
@EpoxyAttribute lateinit var avatarRenderer: AvatarRenderer
|
||||
@EpoxyAttribute lateinit var matrixItem: MatrixItem
|
||||
@EpoxyAttribute var unreadNotificationCount: Int = 0
|
||||
@EpoxyAttribute var showHighlighted: Boolean = false
|
||||
@EpoxyAttribute var hasUnreadMessage: Boolean = false
|
||||
@EpoxyAttribute var hasDraft: Boolean = false
|
||||
@EpoxyAttribute var textDrawableLeft: Drawable? = null
|
||||
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var itemClickListener: View.OnClickListener? = null
|
||||
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var itemLongClickListener: View.OnLongClickListener? = null
|
||||
|
||||
override fun bind(holder: Holder) {
|
||||
super.bind(holder)
|
||||
holder.rootView.setOnClickListener(itemClickListener)
|
||||
holder.rootView.setOnLongClickListener {
|
||||
it.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
|
||||
itemLongClickListener?.onLongClick(it) ?: false
|
||||
}
|
||||
holder.unreadIndentIndicator.isVisible = hasUnreadMessage
|
||||
avatarRenderer.render(matrixItem, holder.avatarImageView)
|
||||
holder.unreadCounterBadgeView.render(UnreadCounterBadgeView.State(unreadNotificationCount, showHighlighted))
|
||||
holder.draftIndentIndicator.isVisible = hasDraft
|
||||
holder.typingIndicator.isVisible = hasTypingUsers
|
||||
holder.roomName.text = if (textDrawableLeft != null) "⭐️ ${matrixItem.getBestName()}" else matrixItem.getBestName()
|
||||
// TODO this drawable don't work
|
||||
// holder.roomName.setCompoundDrawables(textDrawableLeft, null, null, null)
|
||||
}
|
||||
|
||||
override fun unbind(holder: Holder) {
|
||||
holder.rootView.setOnClickListener(null)
|
||||
super.unbind(holder)
|
||||
}
|
||||
|
||||
class Holder : VectorEpoxyHolder() {
|
||||
val unreadCounterBadgeView by bind<UnreadCounterBadgeView>(R.id.itemRoomGridUnreadCounterBadgeView)
|
||||
val unreadIndentIndicator by bind<View>(R.id.itemRoomGridUnreadIndicator)
|
||||
val draftIndentIndicator by bind<View>(R.id.itemRoomGridDraftBadge)
|
||||
val typingIndicator by bind<View>(R.id.itemRoomGridTypingView)
|
||||
val avatarImageView by bind<ImageView>(R.id.itemRoomGridImageView)
|
||||
val roomName by bind<TextView>(R.id.itemRoomGridRoomName)
|
||||
val rootView by bind<ViewGroup>(R.id.itemRoomGridRoot)
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.home.room.list.tabs
|
||||
|
||||
import im.vector.app.core.platform.VectorViewModelAction
|
||||
|
||||
sealed class RoomListTabsAction : VectorViewModelAction
|
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.home.room.list.tabs
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.features.home.HomeActivitySharedAction
|
||||
import im.vector.app.features.home.HomeSharedActionViewModel
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import kotlinx.android.synthetic.main.fragment_room_list_tabs.*
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class RoomListTabsFragment @Inject constructor(
|
||||
private val viewModelFactory: RoomListTabsViewModel.Factory,
|
||||
private val vectorPreferences: VectorPreferences
|
||||
) : VectorBaseFragment(), RoomListTabsViewModel.Factory by viewModelFactory {
|
||||
|
||||
private val viewModel: RoomListTabsViewModel by fragmentViewModel()
|
||||
private lateinit var pagerAdapter: RoomListTabsPagerAdapter
|
||||
private lateinit var sharedActionViewModel: HomeSharedActionViewModel
|
||||
|
||||
override fun getLayoutResId() = R.layout.fragment_room_list_tabs
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
sharedActionViewModel = activityViewModelProvider.get(HomeSharedActionViewModel::class.java)
|
||||
pagerAdapter = RoomListTabsPagerAdapter(this, requireContext(), vectorPreferences)
|
||||
viewPager.adapter = pagerAdapter
|
||||
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
|
||||
val item = pagerAdapter.getTabs()[position]
|
||||
tab.text = getString(item.titleRes).toLowerCase().capitalize()
|
||||
}.attach()
|
||||
|
||||
val onPageChangeListener: ViewPager2.OnPageChangeCallback = object : ViewPager2.OnPageChangeCallback() {
|
||||
override fun onPageSelected(position: Int) {
|
||||
val item = pagerAdapter.getTabs()[position]
|
||||
sharedActionViewModel.post(HomeActivitySharedAction.OnDisplayModeSelected(item))
|
||||
}
|
||||
}
|
||||
viewPager.registerOnPageChangeCallback(onPageChangeListener)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
// Tmp if the labs preference did change
|
||||
pagerAdapter.notifyDataSetChanged()
|
||||
super.onResume()
|
||||
}
|
||||
override fun invalidate() = withState(viewModel) { state ->
|
||||
Timber.v("Invalidate state: $state")
|
||||
}
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.home.room.list.tabs
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
import com.airbnb.mvrx.MvRx
|
||||
import im.vector.app.features.home.RoomListDisplayMode
|
||||
import im.vector.app.features.home.room.list.RoomListFragment
|
||||
import im.vector.app.features.home.room.list.RoomListParams
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
|
||||
class RoomListTabsPagerAdapter(private val fragment: Fragment,
|
||||
private val context: Context,
|
||||
private val vectorPreferences: VectorPreferences) : FragmentStateAdapter(fragment) {
|
||||
|
||||
// companion object {
|
||||
// val TABS = listOf(
|
||||
// RoomListDisplayMode.ALL,
|
||||
// RoomListDisplayMode.FAVORITES,
|
||||
// RoomListDisplayMode.NOTIFICATIONS,
|
||||
// RoomListDisplayMode.ROOMS,
|
||||
// RoomListDisplayMode.PEOPLE,
|
||||
// RoomListDisplayMode.INVITES,
|
||||
// RoomListDisplayMode.LOW_PRIORITY
|
||||
// )
|
||||
// }
|
||||
|
||||
fun getTabs() : List<RoomListDisplayMode> {
|
||||
return ArrayList<RoomListDisplayMode>().apply {
|
||||
add(RoomListDisplayMode.ALL)
|
||||
if (!vectorPreferences.labPinFavInTabNavigation()) {
|
||||
add(RoomListDisplayMode.FAVORITES)
|
||||
}
|
||||
add(RoomListDisplayMode.NOTIFICATIONS)
|
||||
add(RoomListDisplayMode.ROOMS)
|
||||
add(RoomListDisplayMode.PEOPLE)
|
||||
add(RoomListDisplayMode.INVITES)
|
||||
add(RoomListDisplayMode.LOW_PRIORITY)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount() = getTabs().count()
|
||||
|
||||
override fun createFragment(position: Int): Fragment {
|
||||
val roomListFragment = fragment.childFragmentManager.fragmentFactory.instantiate(context.classLoader, RoomListFragment::class.java.name)
|
||||
val displayMode = getTabs()[position]
|
||||
val params = RoomListParams(displayMode)
|
||||
return roomListFragment.apply {
|
||||
arguments = Bundle().apply { putParcelable(MvRx.KEY_ARG, params) }
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.home.room.list.tabs
|
||||
|
||||
import com.airbnb.mvrx.ActivityViewModelContext
|
||||
import com.airbnb.mvrx.FragmentViewModelContext
|
||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||
import com.airbnb.mvrx.ViewModelContext
|
||||
import com.squareup.inject.assisted.Assisted
|
||||
import com.squareup.inject.assisted.AssistedInject
|
||||
import im.vector.app.core.platform.EmptyViewEvents
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import timber.log.Timber
|
||||
|
||||
class RoomListTabsViewModel @AssistedInject constructor(@Assisted initialState: RoomListTabsViewState)
|
||||
: VectorViewModel<RoomListTabsViewState, RoomListTabsAction, EmptyViewEvents>(initialState) {
|
||||
|
||||
@AssistedInject.Factory
|
||||
interface Factory {
|
||||
fun create(initialState: RoomListTabsViewState): RoomListTabsViewModel
|
||||
}
|
||||
|
||||
companion object : MvRxViewModelFactory<RoomListTabsViewModel, RoomListTabsViewState> {
|
||||
|
||||
@JvmStatic
|
||||
override fun create(viewModelContext: ViewModelContext, state: RoomListTabsViewState): RoomListTabsViewModel? {
|
||||
val factory = when (viewModelContext) {
|
||||
is FragmentViewModelContext -> viewModelContext.fragment as? Factory
|
||||
is ActivityViewModelContext -> viewModelContext.activity as? Factory
|
||||
}
|
||||
return factory?.create(state) ?: error("You should let your activity/fragment implements Factory interface")
|
||||
}
|
||||
}
|
||||
|
||||
override fun handle(action: RoomListTabsAction) {
|
||||
Timber.v("Action $action not handled")
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.home.room.list.tabs
|
||||
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
|
||||
data class RoomListTabsViewState(val noop: Boolean = false) : MvRxState
|
@@ -154,6 +154,9 @@ class VectorPreferences @Inject constructor(private val context: Context) {
|
||||
private const val SETTINGS_LABS_MERGE_E2E_ERRORS = "SETTINGS_LABS_MERGE_E2E_ERRORS"
|
||||
const val SETTINGS_LABS_UNREAD_NOTIFICATIONS_AS_TAB = "SETTINGS_LABS_UNREAD_NOTIFICATIONS_AS_TAB"
|
||||
|
||||
const val SETTINGS_LABS_USE_TOP_TAB_NAVIGATION = "SETTINGS_LABS_USE_TOP_TAB_NAVIGATION"
|
||||
const val SETTINGS_LABS_PIN_FAVORITE = "SETTINGS_LABS_PIN_FAVORITE"
|
||||
|
||||
// analytics
|
||||
const val SETTINGS_USE_ANALYTICS_KEY = "SETTINGS_USE_ANALYTICS_KEY"
|
||||
|
||||
@@ -289,6 +292,14 @@ class VectorPreferences @Inject constructor(private val context: Context) {
|
||||
return defaultPrefs.getBoolean(SETTINGS_LABS_UNREAD_NOTIFICATIONS_AS_TAB, false)
|
||||
}
|
||||
|
||||
fun labUseTabNavigation(): Boolean {
|
||||
return defaultPrefs.getBoolean(SETTINGS_LABS_USE_TOP_TAB_NAVIGATION, false)
|
||||
}
|
||||
|
||||
fun labPinFavInTabNavigation(): Boolean {
|
||||
return defaultPrefs.getBoolean(SETTINGS_LABS_PIN_FAVORITE, false)
|
||||
}
|
||||
|
||||
fun failFast(): Boolean {
|
||||
return BuildConfig.DEBUG || (developerMode() && defaultPrefs.getBoolean(SETTINGS_DEVELOPER_MODE_FAIL_FAST_PREFERENCE_KEY, false))
|
||||
}
|
||||
|
@@ -52,7 +52,13 @@ class IncomingShareController @Inject constructor(private val roomSummaryItemFac
|
||||
} else {
|
||||
roomSummaries.forEach { roomSummary ->
|
||||
roomSummaryItemFactory
|
||||
.createRoomItem(roomSummary, data.selectedRoomIds, callback?.let { it::onRoomClicked }, callback?.let { it::onRoomLongClicked })
|
||||
.createRoomItem(
|
||||
roomSummary,
|
||||
data.selectedRoomIds,
|
||||
1,
|
||||
callback?.let { it::onRoomClicked },
|
||||
callback?.let { it::onRoomLongClicked }
|
||||
)
|
||||
.addTo(this)
|
||||
}
|
||||
}
|
||||
|
@@ -30,5 +30,7 @@ interface UiStateRepository {
|
||||
|
||||
fun getDisplayMode(): RoomListDisplayMode
|
||||
|
||||
// fun getHomeDisplayMode(): HomeDisplayMode
|
||||
|
||||
fun storeDisplayMode(displayMode: RoomListDisplayMode)
|
||||
}
|
||||
|
9
vector/src/main/res/drawable/ic_home_bottom_house.xml
Normal file
9
vector/src/main/res/drawable/ic_home_bottom_house.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M2,20.9241V9.4249C2,8.8381 2.2576,8.281 2.7047,7.901L10.7047,1.101C11.4516,0.4662 12.5484,0.4662 13.2953,1.101L21.2953,7.901C21.7424,8.281 22,8.836 22,9.4227V20.9634C22,22.6349 20.6392,23.9836 18.9678,23.9687C15.4826,23.9377 9.654,23.9012 5.0728,23.9489C3.3867,23.9664 2,22.6103 2,20.9241Z"
|
||||
android:fillColor="#03B381"/>
|
||||
</vector>
|
9
vector/src/main/res/drawable/ic_mode_grid_24dp.xml
Normal file
9
vector/src/main/res/drawable/ic_mode_grid_24dp.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M18.4,4H5.6C4.72,4 4,4.72 4,5.6V18.4C4,19.28 4.72,20 5.6,20H18.4C19.28,20 20,19.28 20,18.4V5.6C20,4.72 19.28,4 18.4,4ZM8.8,18.4H5.6V15.2H8.8V18.4ZM8.8,13.6H5.6V10.4H8.8V13.6ZM8.8,8.8H5.6V5.6H8.8V8.8ZM13.6,18.4H10.4V15.2H13.6V18.4ZM13.6,13.6H10.4V10.4H13.6V13.6ZM13.6,8.8H10.4V5.6H13.6V8.8ZM18.4,18.4H15.2V15.2H18.4V18.4ZM18.4,13.6H15.2V10.4H18.4V13.6ZM18.4,8.8H15.2V5.6H18.4V8.8Z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
10
vector/src/main/res/drawable/ic_mode_list_24dp.xml
Normal file
10
vector/src/main/res/drawable/ic_mode_list_24dp.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M4,5C4,5.5523 4.4477,6 5,6C5.5523,6 6,5.5523 6,5C6,4.4477 5.5523,4 5,4C4.4477,4 4,4.4477 4,5ZM8,5C8,5.5523 8.4477,6 9,6H19C19.5523,6 20,5.5523 20,5C20,4.4477 19.5523,4 19,4H9C8.4477,4 8,4.4477 8,5ZM4,9.5C4,10.0523 4.4477,10.5 5,10.5C5.5523,10.5 6,10.0523 6,9.5C6,8.9477 5.5523,8.5 5,8.5C4.4477,8.5 4,8.9477 4,9.5ZM8,9.5C8,10.0523 8.4477,10.5 9,10.5H19C19.5523,10.5 20,10.0523 20,9.5C20,8.9477 19.5523,8.5 19,8.5H9C8.4477,8.5 8,8.9477 8,9.5ZM4,19C4,19.5523 4.4477,20 5,20C5.5523,20 6,19.5523 6,19C6,18.4477 5.5523,18 5,18C4.4477,18 4,18.4477 4,19ZM8,19C8,19.5523 8.4477,20 9,20H19C19.5523,20 20,19.5523 20,19C20,18.4477 19.5523,18 19,18H9C8.4477,18 8,18.4477 8,19ZM6,14.5C6,15.0523 5.5523,15.5 5,15.5C4.4477,15.5 4,15.0523 4,14.5C4,13.9477 4.4477,13.5 5,13.5C5.5523,13.5 6,13.9477 6,14.5ZM20,14.5C20,15.0523 19.5523,15.5 19,15.5H9C8.4477,15.5 8,15.0523 8,14.5C8,13.9477 8.4477,13.5 9,13.5H19C19.5523,13.5 20,13.9477 20,14.5Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
18
vector/src/main/res/drawable/ic_people.xml
Normal file
18
vector/src/main/res/drawable/ic_people.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M19.2,21.6009C22.1147,19.4116 24,15.926 24,12C24,5.3726 18.6274,0 12,0C5.3726,0 0,5.3726 0,12C0,15.926 1.8853,19.4116 4.8,21.6009V21.6008C6.8056,23.1073 9.2985,24 12,24C14.7015,24 17.1944,23.1073 19.2,21.6009ZM12,12.6C13.9882,12.6 15.6,10.8539 15.6,8.7C15.6,6.5461 13.9882,4.8 12,4.8C10.0118,4.8 8.4,6.5461 8.4,8.7C8.4,10.8539 10.0118,12.6 12,12.6ZM12,21.6C14.5944,21.6 16.9484,20.5709 18.6761,18.8986C17.6076,16.2607 15.0211,14.4 12,14.4C8.9789,14.4 6.3924,16.2607 5.3239,18.8986C7.0516,20.5708 9.4056,21.6 12,21.6Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M19.2,21.6009C22.1147,19.4116 24,15.926 24,12C24,5.3726 18.6274,0 12,0C5.3726,0 0,5.3726 0,12C0,15.926 1.8853,19.4116 4.8,21.6009V21.6008C6.8056,23.1073 9.2985,24 12,24C14.7015,24 17.1944,23.1073 19.2,21.6009ZM12,12.6C13.9882,12.6 15.6,10.8539 15.6,8.7C15.6,6.5461 13.9882,4.8 12,4.8C10.0118,4.8 8.4,6.5461 8.4,8.7C8.4,10.8539 10.0118,12.6 12,12.6ZM12,21.6C14.5944,21.6 16.9484,20.5709 18.6761,18.8986C17.6076,16.2607 15.0211,14.4 12,14.4C8.9789,14.4 6.3924,16.2607 5.3239,18.8986C7.0516,20.5708 9.4056,21.6 12,21.6Z"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M19.2,21.6009L20.4012,23.2L20.4012,23.2L19.2,21.6009ZM4.8,21.6009L3.5989,23.2L6.8,25.6045V21.6009H4.8ZM4.8,21.6008L6.0012,20.0017L2.8,17.5972V21.6008H4.8ZM18.6761,18.8986L20.067,20.3356L21.0361,19.3977L20.5298,18.1477L18.6761,18.8986ZM5.3239,18.8986L3.4702,18.1477L2.9639,19.3977L3.933,20.3356L5.3239,18.8986ZM20.4012,23.2C23.7971,20.6492 26,16.5816 26,12H22C22,15.2703 20.4323,18.1739 17.9988,20.0017L20.4012,23.2ZM26,12C26,4.268 19.732,-2 12,-2V2C17.5228,2 22,6.4771 22,12H26ZM12,-2C4.268,-2 -2,4.268 -2,12H2C2,6.4771 6.4771,2 12,2V-2ZM-2,12C-2,16.5816 0.2029,20.6492 3.5989,23.2L6.0012,20.0017C3.5677,18.1739 2,15.2703 2,12H-2ZM2.8,21.6008V21.6009H6.8V21.6008H2.8ZM12,22C9.7465,22 7.6723,21.257 6.0012,20.0017L3.5988,23.2C5.9389,24.9577 8.8506,26 12,26V22ZM17.9988,20.0017C16.3277,21.257 14.2535,22 12,22V26C15.1494,26 18.0611,24.9577 20.4012,23.2L17.9988,20.0017ZM13.6,8.7C13.6,9.9031 12.7359,10.6 12,10.6V14.6C15.2405,14.6 17.6,11.8047 17.6,8.7H13.6ZM12,6.8C12.7359,6.8 13.6,7.4969 13.6,8.7H17.6C17.6,5.5953 15.2405,2.8 12,2.8V6.8ZM10.4,8.7C10.4,7.4969 11.2641,6.8 12,6.8V2.8C8.7595,2.8 6.4,5.5953 6.4,8.7H10.4ZM12,10.6C11.2641,10.6 10.4,9.9031 10.4,8.7H6.4C6.4,11.8047 8.7595,14.6 12,14.6V10.6ZM17.2851,17.4615C15.9154,18.7873 14.0547,19.6 12,19.6V23.6C15.1341,23.6 17.9814,22.3544 20.067,20.3356L17.2851,17.4615ZM12,16.4C14.1788,16.4 16.0492,17.7406 16.8223,19.6494L20.5298,18.1477C19.166,14.7808 15.8634,12.4 12,12.4V16.4ZM7.1777,19.6494C7.9508,17.7406 9.8212,16.4 12,16.4V12.4C8.1366,12.4 4.834,14.7808 3.4702,18.1477L7.1777,19.6494ZM12,19.6C9.9454,19.6 8.0846,18.7873 6.7149,17.4615L3.933,20.3356C6.0186,22.3544 8.8659,23.6 12,23.6V19.6Z"
|
||||
android:fillColor="#000000"/>
|
||||
</group>
|
||||
</vector>
|
18
vector/src/main/res/drawable/ic_tab_chats.xml
Normal file
18
vector/src/main/res/drawable/ic_tab_chats.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:pathData="M5.0426,19.9701C7.5512,19.9701 9.5849,17.9514 9.5849,15.4612C9.5849,12.971 7.5512,10.9523 5.0426,10.9523C2.5339,10.9523 0.5002,12.971 0.5002,15.4612C0.5002,16.1585 0.6597,16.8188 0.9443,17.4081L0.5571,18.6574C0.3188,19.4261 1.0399,20.147 1.8085,19.9085L3.0615,19.5199C3.6602,19.8084 4.3324,19.9701 5.0426,19.9701Z"
|
||||
android:strokeWidth="1"
|
||||
android:fillColor="#0DBD8B"
|
||||
android:fillType="evenOdd"
|
||||
android:strokeColor="#00000000"/>
|
||||
<path
|
||||
android:pathData="M10.322,18.2236C10.755,17.4092 11,16.4819 11,15.4981C11,12.2555 8.3384,9.6269 5.0551,9.6269C3.5162,9.6269 2.1139,10.2044 1.0582,11.152C0.9409,10.5766 0.8794,9.981 0.8794,9.371C0.8794,4.4717 4.8496,0.5 9.7472,0.5C14.6447,0.5 18.6149,4.4717 18.6149,9.371C18.6149,10.7434 18.3034,12.043 17.7472,13.2029L19.042,17.4126C19.2786,18.1818 18.5559,18.9011 17.7878,18.661L13.6142,17.3563C12.6083,17.8447 11.4962,18.1485 10.322,18.2236Z"
|
||||
android:strokeWidth="1"
|
||||
android:fillColor="#0DBD8B"
|
||||
android:fillType="evenOdd"
|
||||
android:strokeColor="#00000000"/>
|
||||
</vector>
|
@@ -1,118 +1,196 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout 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/coordinatorLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/groupToolbar"
|
||||
style="@style/VectorToolbarStyle"
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appBarLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:elevation="4dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
android:layout_height="wrap_content"
|
||||
app:elevation="0dp">
|
||||
|
||||
<LinearLayout
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/groupToolbar"
|
||||
style="@style/VectorToolbarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:elevation="4dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_scrollFlags="scroll|enterAlways">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/groupToolbarAvatarImageView"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:contentDescription="@string/a11y_open_drawer"
|
||||
tools:src="@tools:sample/avatars" />
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/groupToolbarTitleView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?riotx_text_primary"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
<ImageView
|
||||
android:id="@+id/groupToolbarAvatarImageView"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:contentDescription="@string/a11y_open_drawer"
|
||||
tools:src="@tools:sample/avatars" />
|
||||
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:id="@+id/groupToolbarTitleView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
android:textColor="?riotx_text_primary"
|
||||
android:textStyle="bold"
|
||||
app:autoSizeMaxTextSize="16sp"
|
||||
app:autoSizeMinTextSize="10sp"
|
||||
app:autoSizeStepGranularity="1sp"
|
||||
app:autoSizeTextType="uniform"
|
||||
tools:text="@tools:sample/full_names" />
|
||||
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
</LinearLayout>
|
||||
|
||||
<im.vector.app.features.sync.widget.SyncStateView
|
||||
android:id="@+id/syncStateView"
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/groupToolbar" />
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<im.vector.app.core.ui.views.KeysBackupBanner
|
||||
android:id="@+id/homeKeysBackupBanner"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?riotx_keys_backup_banner_accent_color"
|
||||
android:minHeight="67dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/syncStateView" />
|
||||
<im.vector.app.features.sync.widget.SyncStateView
|
||||
android:id="@+id/syncStateView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<im.vector.app.core.ui.views.ActiveCallView
|
||||
android:id="@+id/activeCallView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toBottomOf="@id/homeKeysBackupBanner"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/roomListContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:background="?riotx_header_panel_background"
|
||||
app:layout_constraintBottom_toTopOf="@+id/bottomNavigationView"
|
||||
app:layout_constraintTop_toBottomOf="@+id/activeCallView" />
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/activeCallPiPWrap"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/activeCallView">
|
||||
|
||||
<org.webrtc.SurfaceViewRenderer
|
||||
android:id="@+id/activeCallPiP"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="120dp"
|
||||
<im.vector.app.core.ui.views.KeysBackupBanner
|
||||
android:id="@+id/homeKeysBackupBanner"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?riotx_keys_backup_banner_accent_color"
|
||||
android:minHeight="67dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/syncStateView"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
<im.vector.app.core.ui.views.ActiveCallView
|
||||
android:id="@+id/activeCallView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toBottomOf="@id/homeKeysBackupBanner"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/roomListContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:background="?riotx_header_panel_background"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/activeCallView" />
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/activeCallPiPWrap"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/activeCallView">
|
||||
|
||||
<org.webrtc.SurfaceViewRenderer
|
||||
android:id="@+id/activeCallPiP"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="120dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
<im.vector.app.features.home.room.list.widget.FabMenuView
|
||||
android:id="@+id/createChatFabMenu"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="48dp"
|
||||
android:visibility="gone"
|
||||
app:layoutDescription="@xml/motion_scene_fab_menu"
|
||||
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
|
||||
tools:layout_editor_absoluteX="1dp"
|
||||
tools:layout_editor_absoluteY="-56dp"
|
||||
tools:showPaths="true"
|
||||
tools:visibility="visible" />
|
||||
|
||||
|
||||
<!-- TODO check accessibilityTraversalBefore as we changed layout -->
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/createChatRoomButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="64dp"
|
||||
android:accessibilityTraversalBefore="@+id/roomListView"
|
||||
android:contentDescription="@string/a11y_create_direct_message"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_fab_add_chat"
|
||||
android:visibility="gone"
|
||||
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
|
||||
app:maxImageSize="34dp"
|
||||
tools:layout_marginEnd="80dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<!-- TODO check accessibilityTraversalBefore as we changed layout -->
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/createGroupRoomButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="64dp"
|
||||
android:accessibilityTraversalBefore="@+id/roomListView"
|
||||
android:contentDescription="@string/a11y_create_room"
|
||||
android:src="@drawable/ic_fab_add_room"
|
||||
android:visibility="gone"
|
||||
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
|
||||
app:maxImageSize="32dp"
|
||||
tools:layout_marginEnd="144dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
android:id="@+id/bottomNavigationView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="?riotx_background"
|
||||
app:itemIconSize="20dp"
|
||||
app:itemIconTint="@color/bottom_navigation_icon_tint_selector"
|
||||
app:labelVisibilityMode="unlabeled"
|
||||
app:labelVisibilityMode="labeled"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/roomListContainer"
|
||||
app:layout_insetEdge="bottom"
|
||||
app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior"
|
||||
app:menu="@menu/home_bottom_navigation" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
@@ -5,7 +5,7 @@
|
||||
android:id="@+id/stateView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?riotx_header_panel_background">
|
||||
android:background="?riotx_background">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/roomListView"
|
||||
@@ -13,44 +13,4 @@
|
||||
android:layout_height="match_parent"
|
||||
android:overScrollMode="always" />
|
||||
|
||||
<im.vector.app.features.home.room.list.widget.FabMenuView
|
||||
android:id="@+id/createChatFabMenu"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
app:layoutDescription="@xml/motion_scene_fab_menu"
|
||||
tools:showPaths="true"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/createChatRoomButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:accessibilityTraversalBefore="@+id/roomListView"
|
||||
android:contentDescription="@string/a11y_create_direct_message"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_fab_add_chat"
|
||||
android:visibility="gone"
|
||||
app:maxImageSize="34dp"
|
||||
tools:layout_marginEnd="80dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/createGroupRoomButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:accessibilityTraversalBefore="@+id/roomListView"
|
||||
android:contentDescription="@string/a11y_create_room"
|
||||
android:src="@drawable/ic_fab_add_room"
|
||||
android:visibility="gone"
|
||||
app:maxImageSize="32dp"
|
||||
tools:layout_marginEnd="144dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</im.vector.app.core.platform.StateView>
|
||||
|
22
vector/src/main/res/layout/fragment_room_list_tabs.xml
Normal file
22
vector/src/main/res/layout/fragment_room_list_tabs.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tabLayout"
|
||||
app:tabMode="scrollable"
|
||||
app:tabBackground="?attr/riotx_background"
|
||||
style="@style/Vector.Widget.TabLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/viewPager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
@@ -26,20 +26,20 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginTop="10dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/roomAvatarImageView"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_width="46dp"
|
||||
android:layout_height="46dp"
|
||||
tools:src="@tools:sample/avatars" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/roomAvatarCheckedImageView"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_width="46dp"
|
||||
android:layout_height="46dp"
|
||||
android:scaleType="centerInside"
|
||||
android:src="@drawable/ic_material_done"
|
||||
android:tint="@android:color/white"
|
||||
@@ -54,7 +54,7 @@
|
||||
android:src="@drawable/ic_warning_badge"
|
||||
app:layout_constraintCircle="@id/roomAvatarContainer"
|
||||
app:layout_constraintCircleAngle="45"
|
||||
app:layout_constraintCircleRadius="30dp"
|
||||
app:layout_constraintCircleRadius="20dp"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
<ImageView
|
||||
@@ -63,7 +63,7 @@
|
||||
android:layout_height="24dp"
|
||||
app:layout_constraintCircle="@id/roomAvatarContainer"
|
||||
app:layout_constraintCircleAngle="135"
|
||||
app:layout_constraintCircleRadius="28dp"
|
||||
app:layout_constraintCircleRadius="20dp"
|
||||
tools:ignore="MissingConstraints"
|
||||
tools:src="@drawable/ic_shield_trusted" />
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
<Space
|
||||
android:id="@+id/roomAvatarBottomSpace"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="12dp"
|
||||
android:layout_height="10dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/roomAvatarContainer"
|
||||
tools:layout_marginStart="20dp" />
|
||||
@@ -81,13 +81,13 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/layout_horizontal_margin"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:duplicateParentState="true"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?riotx_text_primary"
|
||||
android:textSize="15sp"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintEnd_toStartOf="@+id/roomDraftBadge"
|
||||
@@ -138,7 +138,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:textColor="?riotx_text_secondary"
|
||||
android:textSize="15sp"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/roomNameView"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/roomNameView"
|
||||
@@ -153,7 +153,7 @@
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textColor="?riotx_text_secondary"
|
||||
android:textSize="15sp"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@+id/roomNameView"
|
||||
app:layout_constraintTop_toBottomOf="@+id/roomNameView"
|
||||
@@ -198,7 +198,7 @@
|
||||
android:background="?riotx_header_panel_border_mobile"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@+id/roomNameView"
|
||||
app:layout_constraintTop_toBottomOf="@+id/roomBottomBarrier" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout 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/roomCategoryRootView"
|
||||
android:layout_width="match_parent"
|
||||
@@ -8,19 +9,15 @@
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingEnd="@dimen/layout_horizontal_margin"
|
||||
android:paddingBottom="4dp">
|
||||
android:paddingEnd="2dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/roomCategoryTitleView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
tools:drawableEnd="@drawable/ic_expand_more_white"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:drawableTint="?riotx_text_secondary"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
@@ -28,12 +25,17 @@
|
||||
android:textColor="?riotx_text_secondary"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:drawableEnd="@drawable/ic_expand_more_white"
|
||||
tools:text="@string/room_participants_header_direct_chats" />
|
||||
|
||||
<im.vector.app.features.home.room.list.UnreadCounterBadgeView
|
||||
android:id="@+id/roomCategoryUnreadCounterBadgeView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:gravity="center"
|
||||
android:minWidth="16dp"
|
||||
android:minHeight="16dp"
|
||||
@@ -41,7 +43,21 @@
|
||||
android:paddingEnd="4dp"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="10sp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/roomCategoryTitleView"
|
||||
app:layout_constraintStart_toEndOf="@+id/roomCategoryTitleView"
|
||||
app:layout_constraintTop_toTopOf="@+id/roomCategoryTitleView"
|
||||
tools:background="@drawable/bg_unread_highlight"
|
||||
tools:text="24" />
|
||||
|
||||
</LinearLayout>
|
||||
<ImageView
|
||||
android:id="@+id/roomCategoryMode"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="0dp"
|
||||
android:scaleType="center"
|
||||
android:tint="?riotx_text_secondary"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@drawable/ic_mode_list_24dp" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
103
vector/src/main/res/layout/item_room_grid.xml
Normal file
103
vector/src/main/res/layout/item_room_grid.xml
Normal file
@@ -0,0 +1,103 @@
|
||||
<?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/itemRoomGridRoot"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?riotx_background"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackground">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemRoomGridUnreadIndicator"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:src="@drawable/circle"
|
||||
android:tint="?attr/colorAccent"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/itemRoomGridImageView"
|
||||
app:layout_constraintEnd_toEndOf="@+id/itemRoomGridImageView"
|
||||
app:layout_constraintStart_toStartOf="@+id/itemRoomGridImageView"
|
||||
app:layout_constraintTop_toTopOf="@+id/itemRoomGridImageView"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemRoomGridImageView"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@tools:sample/avatars" />
|
||||
|
||||
<im.vector.app.features.home.room.list.UnreadCounterBadgeView
|
||||
android:id="@+id/itemRoomGridUnreadCounterBadgeView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:minWidth="18dp"
|
||||
android:minHeight="18dp"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="11sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintCircle="@+id/itemRoomGridImageView"
|
||||
app:layout_constraintCircleAngle="45"
|
||||
app:layout_constraintCircleRadius="28dp"
|
||||
tools:background="@drawable/bg_unread_highlight"
|
||||
tools:ignore="MissingConstraints"
|
||||
tools:text="24"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemRoomGridTypingView"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:background="@drawable/bg_breadcrumbs_typing"
|
||||
android:gravity="center"
|
||||
android:text="@string/ellipsis"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="11sp"
|
||||
android:textStyle="bold"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintCircle="@+id/itemRoomGridImageView"
|
||||
app:layout_constraintCircleAngle="135"
|
||||
app:layout_constraintCircleRadius="28dp"
|
||||
tools:ignore="MissingConstraints"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemRoomGridDraftBadge"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:background="@drawable/circle"
|
||||
android:padding="3dp"
|
||||
android:src="@drawable/ic_edit"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintCircle="@+id/itemRoomGridImageView"
|
||||
app:layout_constraintCircleAngle="225"
|
||||
app:layout_constraintCircleRadius="28dp"
|
||||
tools:ignore="MissingConstraints"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemRoomGridRoomName"
|
||||
android:layout_width="76dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="2dp"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:lines="2"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/itemRoomGridImageView"
|
||||
tools:text="@sample/matrix.json/data/roomName" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
29
vector/src/main/res/layout/to_delete.xml
Normal file
29
vector/src/main/res/layout/to_delete.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<Toolbar
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
<!-- app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior"-->
|
||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
|
||||
android:layout_width="match_parent"
|
||||
app:menu="@menu/home"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
@@ -1,11 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
|
||||
<item
|
||||
android:id="@+id/bottom_action_chats"
|
||||
android:enabled="true"
|
||||
android:icon="@drawable/ic_home_bottom_house"
|
||||
android:title="@string/bottom_action_home" />
|
||||
|
||||
|
||||
<item
|
||||
android:id="@+id/bottom_action_favourites"
|
||||
android:enabled="true"
|
||||
android:icon="@drawable/ic_star_24dp"
|
||||
android:title="@string/bottom_action_favourites" />
|
||||
|
||||
|
||||
<item
|
||||
android:id="@+id/bottom_action_people"
|
||||
android:enabled="true"
|
||||
android:icon="@drawable/ic_home_bottom_chat"
|
||||
android:title="@string/bottom_action_people_x" />
|
||||
android:title="@string/bottom_action_people_short" />
|
||||
|
||||
|
||||
<item
|
||||
android:id="@+id/bottom_action_rooms"
|
||||
@@ -13,6 +29,7 @@
|
||||
android:icon="@drawable/ic_home_bottom_group"
|
||||
android:title="@string/bottom_action_rooms" />
|
||||
|
||||
|
||||
<item
|
||||
android:id="@+id/bottom_action_notification"
|
||||
android:enabled="true"
|
||||
@@ -20,4 +37,12 @@
|
||||
android:title="@string/bottom_action_notification"
|
||||
android:visible="false" />
|
||||
|
||||
|
||||
<!-- <item-->
|
||||
<!-- android:id="@+id/bottom_action_you"-->
|
||||
<!-- android:enabled="true"-->
|
||||
<!-- android:icon="@drawable/ic_people"-->
|
||||
<!-- android:title="@string/home_bottom_tab_you"-->
|
||||
<!-- android:visible="false" />-->
|
||||
|
||||
</menu>
|
||||
|
@@ -144,11 +144,15 @@
|
||||
|
||||
<!-- Bottom navigation buttons -->
|
||||
<string name="bottom_action_home">Home</string>
|
||||
<string name="bottom_action_notification">Notifications</string>
|
||||
<string name="bottom_action_notification">Unread</string>
|
||||
<string name="bottom_action_favourites">Favourites</string>
|
||||
<string name="bottom_action_people">People</string>
|
||||
<string name="bottom_action_rooms">Rooms</string>
|
||||
<string name="bottom_action_groups">Communities</string>
|
||||
<string name="room_list_tabs_all">Chats</string>
|
||||
|
||||
<string name="home_bottom_tab_chats">Chats</string>
|
||||
<string name="home_bottom_tab_you">You</string>
|
||||
|
||||
<!-- Home screen -->
|
||||
<string name="home_filter_placeholder_home">Filter room names</string>
|
||||
@@ -1700,6 +1704,7 @@
|
||||
<string name="settings_labs_show_hidden_events_in_timeline">Show hidden events in timeline</string>
|
||||
|
||||
<string name="bottom_action_people_x">Direct Messages</string>
|
||||
<string name="bottom_action_people_short">DMs</string>
|
||||
|
||||
<string name="send_file_step_idle">Waiting…</string>
|
||||
<string name="send_file_step_encrypting_thumbnail">Encrypting thumbnail…</string>
|
||||
@@ -1727,6 +1732,9 @@
|
||||
<string name="labs_swipe_to_reply_in_timeline">Enable swipe to reply in timeline</string>
|
||||
<string name="labs_merge_e2e_in_timeline">Merge failed to decrypt message in timeline</string>
|
||||
<string name="labs_show_unread_notifications_as_tab">Add a dedicated tab for unread notifications on main screen.</string>
|
||||
<string name="labs_experimental_nav_title">Experimental Navigation</string>
|
||||
<string name="labs_experimental_top_tabs">Use top tabs</string>
|
||||
<string name="labs_experimental_pin_favorites">Pin favorites</string>
|
||||
|
||||
<string name="link_copied_to_clipboard">Link copied to clipboard</string>
|
||||
|
||||
|
8
vector/src/main/res/values/style_tab_layout.xml
Normal file
8
vector/src/main/res/values/style_tab_layout.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="Vector.Widget.TabLayout" parent="Widget.Design.TabLayout">
|
||||
<item name="tabTextAppearance">@style/TextAppearance.Vector.Tabs</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
@@ -3,4 +3,5 @@
|
||||
|
||||
<style name="Vector.PopupMenu" parent="Vector.PopupMenuBase" />
|
||||
|
||||
|
||||
</resources>
|
@@ -60,4 +60,9 @@
|
||||
<item name="android:textColor">?riotx_android_secondary</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Vector.Tabs" parent="TextAppearance.Design.Tab">
|
||||
<item name="textAllCaps">false</item>
|
||||
<item name="android:textAllCaps">false</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
@@ -49,7 +49,22 @@
|
||||
<im.vector.app.core.preference.VectorSwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="SETTINGS_LABS_UNREAD_NOTIFICATIONS_AS_TAB"
|
||||
android:title="@string/labs_show_unread_notifications_as_tab" />
|
||||
android:title="@string/labs_experimental_nav_title" />
|
||||
|
||||
<im.vector.app.core.preference.VectorPreferenceCategory android:title="@string/labs_experimental_nav_title">
|
||||
|
||||
<im.vector.app.core.preference.VectorSwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="SETTINGS_LABS_USE_TOP_TAB_NAVIGATION"
|
||||
android:title="@string/labs_experimental_top_tabs" />
|
||||
|
||||
|
||||
<im.vector.app.core.preference.VectorSwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:dependency="SETTINGS_LABS_USE_TOP_TAB_NAVIGATION"
|
||||
android:key="SETTINGS_LABS_PIN_FAVORITE"
|
||||
android:title="@string/labs_experimental_pin_favorites" />
|
||||
</im.vector.app.core.preference.VectorPreferenceCategory>
|
||||
<!--</im.vector.app.core.preference.VectorPreferenceCategory>-->
|
||||
|
||||
</androidx.preference.PreferenceScreen>
|
Reference in New Issue
Block a user