Dial pad tab: second step, add to home
This commit is contained in:
parent
74497dadd2
commit
771b9b8d78
|
@ -51,7 +51,7 @@ internal class SessionManager @Inject constructor(private val matrixComponent: M
|
|||
}
|
||||
}
|
||||
|
||||
private fun getOrCreateSessionComponent(sessionParams: SessionParams): SessionComponent {
|
||||
fun getOrCreateSessionComponent(sessionParams: SessionParams): SessionComponent {
|
||||
return sessionComponents.getOrPut(sessionParams.credentials.sessionId()) {
|
||||
DaggerSessionComponent
|
||||
.factory()
|
||||
|
|
|
@ -19,6 +19,7 @@ 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 SwitchTab(val tab: HomeTab) : HomeDetailAction()
|
||||
object MarkAllRoomsRead : HomeDetailAction()
|
||||
data class StartCallWithPhoneNumber(val phoneNumber: String): HomeDetailAction()
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.iterator
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
|
@ -41,12 +43,14 @@ import im.vector.app.core.ui.views.KnownCallsViewHolder
|
|||
import im.vector.app.databinding.FragmentHomeDetailBinding
|
||||
import im.vector.app.features.call.SharedKnownCallsViewModel
|
||||
import im.vector.app.features.call.VectorCallActivity
|
||||
import im.vector.app.features.call.dialpad.DialPadFragment
|
||||
import im.vector.app.features.call.webrtc.WebRtcCallManager
|
||||
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.UnreadCounterBadgeView
|
||||
import im.vector.app.features.popup.PopupAlertManager
|
||||
import im.vector.app.features.popup.VerificationVectorAlert
|
||||
import im.vector.app.features.settings.VectorLocale
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import im.vector.app.features.settings.VectorSettingsActivity.Companion.EXTRA_DIRECT_ACCESS_SECURITY_PRIVACY_MANAGE_SESSIONS
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
|
@ -100,6 +104,9 @@ class HomeDetailFragment @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||
withState(viewModel) { state ->
|
||||
menu.iterator().forEach { it.isVisible = state.currentTab is HomeTab.RoomList }
|
||||
}
|
||||
menu.findItem(R.id.menu_home_mark_all_as_read).isVisible = hasUnreadRooms
|
||||
super.onPrepareOptionsMenu(menu)
|
||||
}
|
||||
|
@ -122,7 +129,7 @@ class HomeDetailFragment @Inject constructor(
|
|||
|
||||
withState(viewModel) {
|
||||
// Update the navigation view if needed (for when we restore the tabs)
|
||||
views.bottomNavigationView.selectedItemId = it.displayMode.toMenuId()
|
||||
views.bottomNavigationView.selectedItemId = it.currentTab.toMenuId()
|
||||
}
|
||||
|
||||
viewModel.selectSubscribe(this, HomeDetailViewState::roomGroupingMethod) { roomGroupingMethod ->
|
||||
|
@ -130,14 +137,18 @@ class HomeDetailFragment @Inject constructor(
|
|||
is RoomGroupingMethod.ByLegacyGroup -> {
|
||||
onGroupChange(roomGroupingMethod.groupSummary)
|
||||
}
|
||||
is RoomGroupingMethod.BySpace -> {
|
||||
is RoomGroupingMethod.BySpace -> {
|
||||
onSpaceChange(roomGroupingMethod.spaceSummary)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.selectSubscribe(this, HomeDetailViewState::displayMode) { displayMode ->
|
||||
switchDisplayMode(displayMode)
|
||||
viewModel.selectSubscribe(this, HomeDetailViewState::currentTab) { currentTab ->
|
||||
updateUIForTab(currentTab)
|
||||
}
|
||||
|
||||
viewModel.selectSubscribe(this, HomeDetailViewState::showDialPadTab) { showDialPadTab ->
|
||||
updateTabVisibilitySafely(R.id.bottom_action_dial_pad, showDialPadTab)
|
||||
}
|
||||
|
||||
unknownDeviceDetectorSharedViewModel.subscribe { state ->
|
||||
|
@ -178,21 +189,11 @@ class HomeDetailFragment @Inject constructor(
|
|||
override fun onResume() {
|
||||
super.onResume()
|
||||
// update notification tab if needed
|
||||
checkNotificationTabStatus()
|
||||
updateTabVisibilitySafely(R.id.bottom_action_notification, vectorPreferences.labAddNotificationTab())
|
||||
callManager.checkForProtocolsSupportIfNeeded()
|
||||
}
|
||||
|
||||
private fun checkNotificationTabStatus() {
|
||||
val wasVisible = views.bottomNavigationView.menu.findItem(R.id.bottom_action_notification).isVisible
|
||||
views.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 promptForNewUnknownDevices(uid: String, state: UnknownDevicesState, newest: DeviceInfo) {
|
||||
val user = state.myMatrixItem
|
||||
|
@ -273,10 +274,10 @@ class HomeDetailFragment @Inject constructor(
|
|||
serverBackupStatusViewModel
|
||||
.subscribe(this) {
|
||||
when (val banState = it.bannerState.invoke()) {
|
||||
is BannerState.Setup -> views.homeKeysBackupBanner.render(KeysBackupBanner.State.Setup(banState.numberOfKeys), false)
|
||||
is BannerState.Setup -> views.homeKeysBackupBanner.render(KeysBackupBanner.State.Setup(banState.numberOfKeys), false)
|
||||
BannerState.BackingUp -> views.homeKeysBackupBanner.render(KeysBackupBanner.State.BackingUp, false)
|
||||
null,
|
||||
BannerState.Hidden -> views.homeKeysBackupBanner.render(KeysBackupBanner.State.Hidden, false)
|
||||
BannerState.Hidden -> views.homeKeysBackupBanner.render(KeysBackupBanner.State.Hidden, false)
|
||||
}
|
||||
}
|
||||
views.homeKeysBackupBanner.delegate = this
|
||||
|
@ -307,7 +308,7 @@ class HomeDetailFragment @Inject constructor(
|
|||
is RoomGroupingMethod.ByLegacyGroup -> {
|
||||
// nothing do far
|
||||
}
|
||||
is RoomGroupingMethod.BySpace -> {
|
||||
is RoomGroupingMethod.BySpace -> {
|
||||
it.roomGroupingMethod.spaceSummary?.let {
|
||||
sharedActionViewModel.post(HomeActivitySharedAction.ShowSpaceSettings(it.roomId))
|
||||
}
|
||||
|
@ -320,12 +321,13 @@ class HomeDetailFragment @Inject constructor(
|
|||
private fun setupBottomNavigationView() {
|
||||
views.bottomNavigationView.menu.findItem(R.id.bottom_action_notification).isVisible = vectorPreferences.labAddNotificationTab()
|
||||
views.bottomNavigationView.setOnNavigationItemSelectedListener {
|
||||
val displayMode = when (it.itemId) {
|
||||
R.id.bottom_action_people -> RoomListDisplayMode.PEOPLE
|
||||
R.id.bottom_action_rooms -> RoomListDisplayMode.ROOMS
|
||||
else -> RoomListDisplayMode.NOTIFICATIONS
|
||||
val tab = when (it.itemId) {
|
||||
R.id.bottom_action_people -> HomeTab.RoomList(RoomListDisplayMode.PEOPLE)
|
||||
R.id.bottom_action_rooms -> HomeTab.RoomList(RoomListDisplayMode.ROOMS)
|
||||
R.id.bottom_action_notification -> HomeTab.RoomList(RoomListDisplayMode.NOTIFICATIONS)
|
||||
else -> HomeTab.DialPad
|
||||
}
|
||||
viewModel.handle(HomeDetailAction.SwitchDisplayMode(displayMode))
|
||||
viewModel.handle(HomeDetailAction.SwitchTab(tab))
|
||||
true
|
||||
}
|
||||
|
||||
|
@ -341,13 +343,14 @@ class HomeDetailFragment @Inject constructor(
|
|||
// }
|
||||
}
|
||||
|
||||
private fun switchDisplayMode(displayMode: RoomListDisplayMode) {
|
||||
views.groupToolbarTitleView.setText(displayMode.titleRes)
|
||||
updateSelectedFragment(displayMode)
|
||||
private fun updateUIForTab(tab: HomeTab) {
|
||||
views.groupToolbarTitleView.setText(tab.titleRes)
|
||||
updateSelectedFragment(tab)
|
||||
invalidateOptionsMenu()
|
||||
}
|
||||
|
||||
private fun updateSelectedFragment(displayMode: RoomListDisplayMode) {
|
||||
val fragmentTag = "FRAGMENT_TAG_${displayMode.name}"
|
||||
private fun updateSelectedFragment(tab: HomeTab) {
|
||||
val fragmentTag = "FRAGMENT_TAG_$tab"
|
||||
val fragmentToShow = childFragmentManager.findFragmentByTag(fragmentTag)
|
||||
childFragmentManager.commitTransaction {
|
||||
childFragmentManager.fragments
|
||||
|
@ -356,14 +359,46 @@ class HomeDetailFragment @Inject constructor(
|
|||
detach(it)
|
||||
}
|
||||
if (fragmentToShow == null) {
|
||||
val params = RoomListParams(displayMode)
|
||||
add(R.id.roomListContainer, RoomListFragment::class.java, params.toMvRxBundle(), fragmentTag)
|
||||
if (tab is HomeTab.RoomList) {
|
||||
val params = RoomListParams(tab.displayMode)
|
||||
add(R.id.roomListContainer, RoomListFragment::class.java, params.toMvRxBundle(), fragmentTag)
|
||||
} else {
|
||||
add(R.id.roomListContainer, createDialPadFragment())
|
||||
}
|
||||
} else {
|
||||
if (tab is HomeTab.DialPad) {
|
||||
(fragmentToShow as? DialPadFragment)?.applyCallback()
|
||||
}
|
||||
attach(fragmentToShow)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createDialPadFragment(): Fragment {
|
||||
val fragment = childFragmentManager.fragmentFactory.instantiate(vectorBaseActivity.classLoader, DialPadFragment::class.java.name)
|
||||
return (fragment as DialPadFragment).apply {
|
||||
arguments = Bundle().apply {
|
||||
putBoolean(DialPadFragment.EXTRA_ENABLE_DELETE, true)
|
||||
putBoolean(DialPadFragment.EXTRA_ENABLE_OK, true)
|
||||
putString(DialPadFragment.EXTRA_REGION_CODE, VectorLocale.applicationLocale.country)
|
||||
}
|
||||
applyCallback()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateTabVisibilitySafely(tabId: Int, isVisible: Boolean) {
|
||||
val wasVisible = views.bottomNavigationView.menu.findItem(tabId).isVisible
|
||||
views.bottomNavigationView.menu.findItem(tabId).isVisible = isVisible
|
||||
if (wasVisible && !isVisible) {
|
||||
// As we hide it check if it's not the current item!
|
||||
withState(viewModel) {
|
||||
if (it.currentTab.toMenuId() == tabId) {
|
||||
viewModel.handle(HomeDetailAction.SwitchTab(HomeTab.RoomList(RoomListDisplayMode.PEOPLE)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ==========================================================================================
|
||||
* KeysBackupBanner Listener
|
||||
* ========================================================================================== */
|
||||
|
@ -398,10 +433,13 @@ 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 HomeTab.toMenuId() = when (this) {
|
||||
is HomeTab.DialPad -> R.id.bottom_action_dial_pad
|
||||
is HomeTab.RoomList -> when (displayMode) {
|
||||
RoomListDisplayMode.PEOPLE -> R.id.bottom_action_people
|
||||
RoomListDisplayMode.ROOMS -> R.id.bottom_action_rooms
|
||||
else -> R.id.bottom_action_notification
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTapToReturnToCall() {
|
||||
|
@ -420,6 +458,16 @@ class HomeDetailFragment @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun DialPadFragment.applyCallback(): DialPadFragment {
|
||||
callback = object : DialPadFragment.Callback {
|
||||
override fun onOkClicked(formatted: String?, raw: String?) {
|
||||
if (raw.isNullOrEmpty()) return
|
||||
viewModel.handle(HomeDetailAction.StartCallWithPhoneNumber(raw))
|
||||
}
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
override fun create(initialState: ServerBackupStatusViewState): ServerBackupStatusViewModel {
|
||||
return serverBackupStatusViewModelFactory.create(initialState)
|
||||
}
|
||||
|
|
|
@ -28,6 +28,11 @@ import im.vector.app.RoomGroupingMethod
|
|||
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.features.call.dialpad.DialPadLookup
|
||||
import im.vector.app.features.call.lookup.CallProtocolsChecker
|
||||
import im.vector.app.features.call.webrtc.WebRtcCallManager
|
||||
import im.vector.app.features.createdirect.DirectRoomHelper
|
||||
import im.vector.app.features.home.room.detail.RoomDetailViewEvents
|
||||
import im.vector.app.features.ui.UiStateRepository
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
@ -51,8 +56,11 @@ import java.util.concurrent.TimeUnit
|
|||
class HomeDetailViewModel @AssistedInject constructor(@Assisted initialState: HomeDetailViewState,
|
||||
private val session: Session,
|
||||
private val uiStateRepository: UiStateRepository,
|
||||
private val callManager: WebRtcCallManager,
|
||||
private val directRoomHelper: DirectRoomHelper,
|
||||
private val appStateHandler: AppStateHandler)
|
||||
: VectorViewModel<HomeDetailViewState, HomeDetailAction, EmptyViewEvents>(initialState) {
|
||||
: VectorViewModel<HomeDetailViewState, HomeDetailAction, EmptyViewEvents>(initialState),
|
||||
CallProtocolsChecker.Listener {
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
|
@ -64,7 +72,7 @@ class HomeDetailViewModel @AssistedInject constructor(@Assisted initialState: Ho
|
|||
override fun initialState(viewModelContext: ViewModelContext): HomeDetailViewState? {
|
||||
val uiStateRepository = (viewModelContext.activity as HasScreenInjector).injector().uiStateRepository()
|
||||
return HomeDetailViewState(
|
||||
displayMode = uiStateRepository.getDisplayMode()
|
||||
currentTab = HomeTab.RoomList(uiStateRepository.getDisplayMode())
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -79,7 +87,8 @@ class HomeDetailViewModel @AssistedInject constructor(@Assisted initialState: Ho
|
|||
observeSyncState()
|
||||
observeRoomGroupingMethod()
|
||||
observeRoomSummaries()
|
||||
|
||||
updateShowDialPadTab()
|
||||
callManager.addProtocolsCheckerListener(this)
|
||||
session.rx().liveUser(session.myUserId).execute {
|
||||
copy(
|
||||
myMatrixItem = it.invoke()?.getOrNull()?.toMatrixItem()
|
||||
|
@ -89,21 +98,50 @@ class HomeDetailViewModel @AssistedInject constructor(@Assisted initialState: Ho
|
|||
|
||||
override fun handle(action: HomeDetailAction) {
|
||||
when (action) {
|
||||
is HomeDetailAction.SwitchDisplayMode -> handleSwitchDisplayMode(action)
|
||||
is HomeDetailAction.SwitchTab -> handleSwitchTab(action)
|
||||
HomeDetailAction.MarkAllRoomsRead -> handleMarkAllRoomsRead()
|
||||
is HomeDetailAction.StartCallWithPhoneNumber -> handleStartCallWithPhoneNumber(action)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSwitchDisplayMode(action: HomeDetailAction.SwitchDisplayMode) = withState { state ->
|
||||
if (state.displayMode != action.displayMode) {
|
||||
setState {
|
||||
copy(displayMode = action.displayMode)
|
||||
private fun handleStartCallWithPhoneNumber(action: HomeDetailAction.StartCallWithPhoneNumber) {
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val result = DialPadLookup(session, callManager, directRoomHelper).lookupPhoneNumber(action.phoneNumber)
|
||||
callManager.startOutgoingCall(result.roomId, result.userId, isVideoCall = false)
|
||||
} catch (failure: Throwable) {
|
||||
Timber.v(failure)
|
||||
}
|
||||
|
||||
uiStateRepository.storeDisplayMode(action.displayMode)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSwitchTab(action: HomeDetailAction.SwitchTab) = withState { state ->
|
||||
if (state.currentTab != action.tab) {
|
||||
setState {
|
||||
copy(currentTab = action.tab)
|
||||
}
|
||||
if(action.tab is HomeTab.RoomList) {
|
||||
uiStateRepository.storeDisplayMode(action.tab.displayMode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
callManager.removeProtocolsCheckerListener(this)
|
||||
}
|
||||
|
||||
override fun onPSTNSupportUpdated() {
|
||||
updateShowDialPadTab()
|
||||
}
|
||||
|
||||
private fun updateShowDialPadTab() {
|
||||
setState {
|
||||
copy(showDialPadTab = callManager.supportsPSTNProtocol)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// PRIVATE METHODS *****************************************************************************
|
||||
|
||||
private fun handleMarkAllRoomsRead() = withState { _ ->
|
||||
|
|
|
@ -16,9 +16,11 @@
|
|||
|
||||
package im.vector.app.features.home
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import com.airbnb.mvrx.Async
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import im.vector.app.R
|
||||
import im.vector.app.RoomGroupingMethod
|
||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||
import org.matrix.android.sdk.api.session.sync.SyncState
|
||||
|
@ -28,7 +30,7 @@ data class HomeDetailViewState(
|
|||
val roomGroupingMethod: RoomGroupingMethod = RoomGroupingMethod.BySpace(null),
|
||||
val myMatrixItem: MatrixItem? = null,
|
||||
val asyncRooms: Async<List<RoomSummary>> = Uninitialized,
|
||||
val displayMode: RoomListDisplayMode = RoomListDisplayMode.PEOPLE,
|
||||
val currentTab: HomeTab = HomeTab.RoomList(RoomListDisplayMode.PEOPLE),
|
||||
val notificationCountCatchup: Int = 0,
|
||||
val notificationHighlightCatchup: Boolean = false,
|
||||
val notificationCountPeople: Int = 0,
|
||||
|
@ -36,5 +38,12 @@ data class HomeDetailViewState(
|
|||
val notificationCountRooms: Int = 0,
|
||||
val notificationHighlightRooms: Boolean = false,
|
||||
val hasUnreadMessages: Boolean = false,
|
||||
val syncState: SyncState = SyncState.Idle
|
||||
val syncState: SyncState = SyncState.Idle,
|
||||
val showDialPadTab: Boolean = false
|
||||
) : MvRxState
|
||||
|
||||
sealed class HomeTab(@StringRes val titleRes: Int) {
|
||||
data class RoomList(val displayMode: RoomListDisplayMode) : HomeTab(displayMode.titleRes)
|
||||
object DialPad : HomeTab(R.string.call_dial_pad_title)
|
||||
}
|
||||
|
||||
|
|
|
@ -20,4 +20,11 @@
|
|||
android:title="@string/bottom_action_notification"
|
||||
android:visible="false" />
|
||||
|
||||
<item
|
||||
android:id="@+id/bottom_action_dial_pad"
|
||||
android:enabled="true"
|
||||
android:icon="@drawable/ic_call_dial_pad"
|
||||
android:title="@string/call_dial_pad_title"
|
||||
android:visible="false" />
|
||||
|
||||
</menu>
|
||||
|
|
Loading…
Reference in New Issue