Skip to content

Commit

Permalink
do not redirect user to the main screen if he has conversations
Browse files Browse the repository at this point in the history
  • Loading branch information
migulyaev committed Oct 4, 2023
1 parent 18e2741 commit 413ab5e
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,22 @@ import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
import tech.relaycorp.letro.contacts.storage.repository.ContactsRepository
import tech.relaycorp.letro.conversation.model.ExtendedConversation
import tech.relaycorp.letro.conversation.storage.repository.ConversationsRepository
import tech.relaycorp.letro.ui.navigation.Route
import tech.relaycorp.letro.utils.ext.emitOn
import javax.inject.Inject

@HiltViewModel
class ConversationViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle,
private val conversationsRepository: ConversationsRepository,
private val contactsRepository: ContactsRepository,
) : ViewModel() {

private val conversationId: String = savedStateHandle[Route.Conversation.KEY_CONVERSATION_ID]!!
Expand All @@ -26,10 +30,23 @@ class ConversationViewModel @Inject constructor(
val deleteConversationDialogState: StateFlow<DeleteConversationDialogState>
get() = _deleteConversationDialogState


private val _showNoContactsSnackbarSignal: MutableSharedFlow<Unit> = MutableSharedFlow()
val showNoContactsSnackbarSignal: MutableSharedFlow<Unit>
get() = _showNoContactsSnackbarSignal

init {
conversationsRepository.markConversationAsRead(conversationId)
}

fun canReply(): Boolean {
val canReply = contactsRepository.contactsState.value.isPairedContactExist
if (!canReply) {
_showNoContactsSnackbarSignal.emitOn(Unit, viewModelScope)
}
return canReply
}

fun onDeleteConversationClick() {
_deleteConversationDialogState.update {
it.copy(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ fun ConversationScreen(
onConversationArchived: (Boolean) -> Unit,
onBackClicked: () -> Unit,
onAttachmentClick: (UUID) -> Unit,
showAddContactSnackbar: () -> Unit,
viewModel: ConversationViewModel = hiltViewModel(),
) {
val scrollState = rememberLazyListState()
Expand All @@ -70,6 +71,12 @@ fun ConversationScreen(

val deleteConversationDialogState by viewModel.deleteConversationDialogState.collectAsState()

LaunchedEffect(Unit) {
viewModel.showNoContactsSnackbarSignal.collect {
showAddContactSnackbar()
}
}

if (conversation != null) {
LaunchedEffect(Unit) { // Scroll to the top of a conversation on screen opening
scrollState.scrollToItem(conversation.messages.size - 1)
Expand Down Expand Up @@ -97,7 +104,11 @@ fun ConversationScreen(
) {
ConversationToolbar(
isArchived = conversation.isArchived,
onReplyClick = onReplyClick,
onReplyClick = {
if (viewModel.canReply()) {
onReplyClick()
}
},
onBackClicked = onBackClicked,
onArchiveClick = {
val isArchived = viewModel.onArchiveConversationClicked()
Expand Down
9 changes: 6 additions & 3 deletions app/src/main/java/tech/relaycorp/letro/main/MainViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import tech.relaycorp.letro.contacts.storage.repository.ContactsRepository
import tech.relaycorp.letro.conversation.attachments.AttachmentsRepository
import tech.relaycorp.letro.conversation.attachments.filepicker.FileConverter
import tech.relaycorp.letro.conversation.attachments.filepicker.model.File
import tech.relaycorp.letro.conversation.storage.repository.ConversationsRepository
import tech.relaycorp.letro.main.di.TermsAndConditionsLink
import tech.relaycorp.letro.push.model.PushAction
import tech.relaycorp.letro.ui.navigation.RootNavigationScreen
Expand All @@ -40,6 +41,7 @@ class MainViewModel @Inject constructor(
private val contactsRepository: ContactsRepository,
private val attachmentsRepository: AttachmentsRepository,
private val fileConverter: FileConverter,
private val conversationsRepository: ConversationsRepository,
@TermsAndConditionsLink private val termsAndConditionsLink: String,
) : ViewModel() {

Expand Down Expand Up @@ -94,8 +96,9 @@ class MainViewModel @Inject constructor(
accountRepository.currentAccount,
contactsRepository.contactsState,
awalaManager.awalaInitializationState,
) { currentAccount, contactsState, awalaInitializationState ->
Log.d(TAG, "$currentAccount; $contactsState; $awalaInitializationState")
conversationsRepository.conversations,
) { currentAccount, contactsState, awalaInitializationState, conversations ->
Log.d(TAG, "$currentAccount; $contactsState; $awalaInitializationState; ${conversations.size}")
when {
awalaInitializationState == AwalaInitializationState.AWALA_NOT_INSTALLED -> RootNavigationScreen.AwalaNotInstalled
awalaInitializationState == AwalaInitializationState.INITIALIZATION_NONFATAL_ERROR -> RootNavigationScreen.AwalaInitializationError(isFatal = false)
Expand All @@ -104,7 +107,7 @@ class MainViewModel @Inject constructor(
currentAccount == null -> RootNavigationScreen.Registration
!currentAccount.isCreated -> RootNavigationScreen.RegistrationWaiting
!contactsState.isPairRequestWasEverSent -> RootNavigationScreen.WelcomeToLetro
!contactsState.isPairedContactExist -> RootNavigationScreen.NoContactsScreen
!contactsState.isPairedContactExist && conversations.isEmpty() -> RootNavigationScreen.NoContactsScreen
else -> RootNavigationScreen.Home
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import tech.relaycorp.letro.contacts.storage.repository.ContactsRepository
import tech.relaycorp.letro.main.home.badge.UnreadBadgesManager
import tech.relaycorp.letro.main.home.ui.HomeFloatingActionButtonConfig
import javax.inject.Inject

@HiltViewModel
class HomeViewModel @Inject constructor(
private val unreadBadgesManager: UnreadBadgesManager,
private val contactsRepository: ContactsRepository,
) : ViewModel() {

private val _uiState = MutableStateFlow(HomeUiState())
Expand All @@ -27,6 +29,10 @@ class HomeViewModel @Inject constructor(
val createNewConversationSignal: SharedFlow<Unit>
get() = _createNewConversationSignal

private val _showNoContactsSnackbarSignal: MutableSharedFlow<Unit> = MutableSharedFlow()
val showNoContactsSnackbarSignal: MutableSharedFlow<Unit>
get() = _showNoContactsSnackbarSignal

init {
viewModelScope.launch {
unreadBadgesManager.unreadConversations.collect {
Expand Down Expand Up @@ -70,7 +76,11 @@ class HomeViewModel @Inject constructor(
viewModelScope.launch {
when (uiState.value.currentTab) {
TAB_CHATS -> {
_createNewConversationSignal.emit(Unit)
if (contactsRepository.contactsState.value.isPairedContactExist) {
_createNewConversationSignal.emit(Unit)
} else {
_showNoContactsSnackbarSignal.emit(Unit)
}
}
TAB_CONTACTS -> {
_uiState.update {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ fun LetroButton(
},
contentColor = when (buttonType) {
ButtonType.Filled -> MaterialTheme.colorScheme.onPrimary
ButtonType.Outlined -> MaterialTheme.colorScheme.onSurface
ButtonType.Outlined -> MaterialTheme.colorScheme.primary
},
disabledContainerColor = LetroColor.disabledButtonBackgroundColor(),
disabledContentColor = LetroColor.disabledButtonTextColor(),
Expand Down Expand Up @@ -71,7 +71,6 @@ fun LetroButton(
Text(
text = text,
style = MaterialTheme.typography.LabelLargeProminent,
color = contentColor,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import com.google.accompanist.systemuicontroller.SystemUiController
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
Expand Down Expand Up @@ -119,6 +120,20 @@ fun LetroNavHost(
}
}

LaunchedEffect(Unit) {
homeViewModel.showNoContactsSnackbarSignal.collect {
showSnackbar(
scope = this,
snackbarHostState = snackbarHostState,
message = stringsProvider.snackbar.youNeedAtLeastOneContact,
actionLabel = stringsProvider.snackbar.addContact,
onActionPerformed = {
navController.navigate(Route.ManageContact.getRouteName(ManageContactViewModel.Type.NEW_CONTACT))
}
)
}
}

LaunchedEffect(isHomeScreenInitialized) {
if (!isHomeScreenInitialized) {
return@LaunchedEffect
Expand Down Expand Up @@ -283,7 +298,7 @@ fun LetroNavHost(
val result = snackbarHostState.showSnackbar(
message = stringsProvider.snackbar.notificationPermissionDenied,
actionLabel = stringsProvider.snackbar.goToSettings,
duration = SnackbarDuration.Long,
duration = SnackbarDuration.Short,
)
if (result == SnackbarResult.ActionPerformed) {
onGoToNotificationsSettingsClick()
Expand Down Expand Up @@ -391,6 +406,17 @@ fun LetroNavHost(
onAttachmentClick = { fileId ->
mainViewModel.onAttachmentClick(fileId)
},
showAddContactSnackbar = {
showSnackbar(
scope = scope,
snackbarHostState = snackbarHostState,
message = stringsProvider.snackbar.youNoLongerConnected,
actionLabel = stringsProvider.snackbar.addContact,
onActionPerformed = {
navController.navigate(Route.ManageContact.getRouteName(ManageContactViewModel.Type.NEW_CONTACT))
}
)
}
)
}
composable(Route.Settings.name) {
Expand Down Expand Up @@ -469,6 +495,25 @@ fun LetroNavHost(
)
}

private fun showSnackbar(
scope: CoroutineScope,
snackbarHostState: SnackbarHostState,
message: String,
actionLabel: String,
onActionPerformed: () -> Unit,
) {
scope.launch {
val result = snackbarHostState.showSnackbar(
message = message,
actionLabel = actionLabel,
duration = SnackbarDuration.Short,
)
if (result == SnackbarResult.ActionPerformed) {
onActionPerformed()
}
}
}

private fun handleFirstNavigation(
navController: NavHostController,
firstNavigation: RootNavigationScreen,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ interface SnackbarStringsProvider {
val notificationPermissionDenied: String
val goToSettings: String
val accountDeleted: String
val youNeedAtLeastOneContact: String
val youNoLongerConnected: String
val addContact: String
}

class SnackbarStringsProviderImpl @Inject constructor(
Expand Down Expand Up @@ -46,4 +49,13 @@ class SnackbarStringsProviderImpl @Inject constructor(

override val accountDeleted: String
get() = activity.getString(R.string.account_deleted)

override val youNeedAtLeastOneContact: String
get() = activity.getString(R.string.you_need_at_least_one_contact)

override val addContact: String
get() = activity.getString(R.string.general_pair_with_others)

override val youNoLongerConnected: String
get() = activity.getString(R.string.you_cannot_reply_not_connected)
}
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@
<string name="switch_accounts">Switch accounts</string>
<string name="content_description_selected_item">Selected item</string>
<string name="content_description_unselected_item">Unselected item</string>

<string name="you_need_at_least_one_contact">You need at least one contact to start a conversation</string>
<string name="you_cannot_reply_not_connected">You can\'t reply to this user because you\'re no longer connected.</string>

<string name="file_size_megabytes" translatable="false">%s MB</string>
<string name="file_size_kilobytes" translatable="false">%s KB</string>
Expand Down

0 comments on commit 413ab5e

Please sign in to comment.