diff --git a/app/src/main/java/com/nextcloud/talk/api/NcApiCoroutines.kt b/app/src/main/java/com/nextcloud/talk/api/NcApiCoroutines.kt index ccca322a766..21b3e4a998c 100644 --- a/app/src/main/java/com/nextcloud/talk/api/NcApiCoroutines.kt +++ b/app/src/main/java/com/nextcloud/talk/api/NcApiCoroutines.kt @@ -10,6 +10,7 @@ package com.nextcloud.talk.api import com.nextcloud.talk.models.json.autocomplete.AutocompleteOverall import com.nextcloud.talk.models.json.conversations.RoomOverall import com.nextcloud.talk.models.json.generic.GenericOverall +import com.nextcloud.talk.models.json.participants.AddParticipantOverall import retrofit2.http.Field import retrofit2.http.FormUrlEncoded import retrofit2.http.GET @@ -65,4 +66,11 @@ interface NcApiCoroutines { @Url url: String, @Field("description") description: String? ): GenericOverall + + @POST + fun addParticipant( + @Header("Authorization") authorization: String?, + @Url url: String?, + @QueryMap options: Map? + ): AddParticipantOverall } diff --git a/app/src/main/java/com/nextcloud/talk/contacts/ContactsActivityCompose.kt b/app/src/main/java/com/nextcloud/talk/contacts/ContactsActivityCompose.kt index 9a2c1d381cf..b35ce93c5bb 100644 --- a/app/src/main/java/com/nextcloud/talk/contacts/ContactsActivityCompose.kt +++ b/app/src/main/java/com/nextcloud/talk/contacts/ContactsActivityCompose.kt @@ -81,8 +81,7 @@ class ContactsActivityCompose : BaseActivity() { listOf( ShareType.Group.shareType, ShareType.Email.shareType, - ShareType - .Circle.shareType + ShareType.Circle.shareType ) ) contactsViewModel.getContactsFromSearchParams() @@ -123,9 +122,9 @@ fun ContactItemRow( contact: AutocompleteUser, contactsViewModel: ContactsViewModel, context: Context, - selectedContacts: MutableList + selectedContacts: MutableList ) { - val isSelected = contact.id?.let { it in selectedContacts } ?: false + val isSelected = contact in selectedContacts val roomUiState by contactsViewModel.roomViewState.collectAsState() val isAddParticipants = contactsViewModel.isAddParticipantsView.value Row( @@ -141,10 +140,11 @@ fun ContactItemRow( ) } else { if (isSelected) { - selectedContacts.remove(contact.id!!) + selectedContacts.remove(contact) } else { - selectedContacts.add(contact.id!!) + selectedContacts.add(contact) } + contactsViewModel.updateSelectedParticipants(selectedContacts) } }, verticalAlignment = Alignment.CenterVertically @@ -200,7 +200,6 @@ fun AppBar(title: String, context: Context, contactsViewModel: ContactsViewModel TopAppBar( title = { Text(text = title) }, - navigationIcon = { IconButton(onClick = { (context as? Activity)?.finish() @@ -304,8 +303,6 @@ fun ConversationCreationOptions(context: Context, contactsViewModel: ContactsVie } } - - class CompanionClass { companion object { internal val TAG = ContactsActivityCompose::class.simpleName diff --git a/app/src/main/java/com/nextcloud/talk/contacts/ContactsActivityViewModel.kt b/app/src/main/java/com/nextcloud/talk/contacts/ContactsActivityViewModel.kt deleted file mode 100644 index 6c87c660896..00000000000 --- a/app/src/main/java/com/nextcloud/talk/contacts/ContactsActivityViewModel.kt +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Nextcloud Talk - Android Client - * - * SPDX-FileCopyrightText: 2024 Your Name - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -package com.nextcloud.talk.contacts - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.nextcloud.talk.data.user.model.User -import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser -import com.nextcloud.talk.models.json.conversations.Conversation -import com.nextcloud.talk.users.UserManager -import com.nextcloud.talk.utils.ApiUtils -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch -import javax.inject.Inject - -class ContactsActivityViewModel @Inject constructor( - private val repository: ContactsRepository, - private val userManager: UserManager -) : ViewModel() { - - private val _contactsViewState = MutableStateFlow(ContactsUiState.None) - val contactsViewState: StateFlow = _contactsViewState - private val _roomViewState = MutableStateFlow(RoomUiState.None) - val roomViewState: StateFlow = _roomViewState - private val _currentUser = userManager.currentUser.blockingGet() - val currentUser: User = _currentUser - private val _searchQuery = MutableStateFlow("") - val searchQuery: StateFlow = _searchQuery - private val shareTypes: MutableList = mutableListOf(ShareType.User.shareType) - val shareTypeList: List = shareTypes - - init { - getContactsFromSearchParams() - } - - fun updateSearchQuery(query: String) { - _searchQuery.value = query - } - - fun updateShareTypes(value: String) { - shareTypes.add(value) - } - - fun getContactsFromSearchParams() { - _contactsViewState.value = ContactsUiState.Loading - viewModelScope.launch { - try { - val contacts = repository.getContacts( - searchQuery.value, - shareTypeList - ) - val contactsList: List? = contacts.ocs!!.data - _contactsViewState.value = ContactsUiState.Success(contactsList) - } catch (exception: Exception) { - _contactsViewState.value = ContactsUiState.Error(exception.message ?: "") - } - } - } - - fun createRoom(roomType: String, sourceType: String, userId: String, conversationName: String?) { - viewModelScope.launch { - try { - val room = repository.createRoom( - roomType, - sourceType, - userId, - conversationName - ) - - val conversation: Conversation? = room.ocs?.data - _roomViewState.value = RoomUiState.Success(conversation) - } catch (exception: Exception) { - _roomViewState.value = RoomUiState.Error(exception.message ?: "") - } - } - } - - fun getImageUri(avatarId: String, requestBigSize: Boolean): String { - return ApiUtils.getUrlForAvatar( - _currentUser.baseUrl, - avatarId, - requestBigSize - ) - } -} - -sealed class ContactsUiState { - data object None : ContactsUiState() - data object Loading : ContactsUiState() - data class Success(val contacts: List?) : ContactsUiState() - data class Error(val message: String) : ContactsUiState() -} - -sealed class RoomUiState { - data object None : RoomUiState() - data class Success(val conversation: Conversation?) : RoomUiState() - data class Error(val message: String) : RoomUiState() -} diff --git a/app/src/main/java/com/nextcloud/talk/contacts/ContactsRepository.kt b/app/src/main/java/com/nextcloud/talk/contacts/ContactsRepository.kt index 8655b79e136..b1e224474f8 100644 --- a/app/src/main/java/com/nextcloud/talk/contacts/ContactsRepository.kt +++ b/app/src/main/java/com/nextcloud/talk/contacts/ContactsRepository.kt @@ -9,9 +9,11 @@ package com.nextcloud.talk.contacts import com.nextcloud.talk.models.json.autocomplete.AutocompleteOverall import com.nextcloud.talk.models.json.conversations.RoomOverall +import com.nextcloud.talk.models.json.participants.AddParticipantOverall interface ContactsRepository { suspend fun getContacts(searchQuery: String?, shareTypes: List): AutocompleteOverall suspend fun createRoom(roomType: String, sourceType: String, userId: String, conversationName: String?): RoomOverall fun getImageUri(avatarId: String, requestBigSize: Boolean): String + suspend fun addParticipants(conversationToken: String, userId: String, sourceType: String): AddParticipantOverall } diff --git a/app/src/main/java/com/nextcloud/talk/contacts/ContactsRepositoryImpl.kt b/app/src/main/java/com/nextcloud/talk/contacts/ContactsRepositoryImpl.kt index 6fcd2751244..8d0af8656b3 100644 --- a/app/src/main/java/com/nextcloud/talk/contacts/ContactsRepositoryImpl.kt +++ b/app/src/main/java/com/nextcloud/talk/contacts/ContactsRepositoryImpl.kt @@ -12,8 +12,11 @@ import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.models.RetrofitBucket import com.nextcloud.talk.models.json.autocomplete.AutocompleteOverall import com.nextcloud.talk.models.json.conversations.RoomOverall +import com.nextcloud.talk.models.json.participants.AddParticipantOverall import com.nextcloud.talk.users.UserManager import com.nextcloud.talk.utils.ApiUtils +import com.nextcloud.talk.utils.ApiUtils.getRetrofitBucketForAddParticipant +import com.nextcloud.talk.utils.ApiUtils.getRetrofitBucketForAddParticipantWithSource import com.nextcloud.talk.utils.ContactUtils class ContactsRepositoryImpl( @@ -72,4 +75,28 @@ class ContactsRepositoryImpl( requestBigSize ) } + + override suspend fun addParticipants( + conversationToken: String, + userId: String, + sourceType: String + ): AddParticipantOverall { + val retrofitBucket: RetrofitBucket = if (sourceType == "users") { + getRetrofitBucketForAddParticipant( + apiVersion, + _currentUser.baseUrl, + conversationToken, + userId + ) + } else { + getRetrofitBucketForAddParticipantWithSource( + apiVersion, + _currentUser.baseUrl, + conversationToken, + sourceType, + userId + ) + } + return ncApiCoroutines.addParticipant(credentials, retrofitBucket.url, retrofitBucket.queryMap) + } } diff --git a/app/src/main/java/com/nextcloud/talk/contacts/ContactsViewModel.kt b/app/src/main/java/com/nextcloud/talk/contacts/ContactsViewModel.kt index cfb307c0f82..fe553a277d5 100644 --- a/app/src/main/java/com/nextcloud/talk/contacts/ContactsViewModel.kt +++ b/app/src/main/java/com/nextcloud/talk/contacts/ContactsViewModel.kt @@ -24,6 +24,8 @@ class ContactsViewModel @Inject constructor( val contactsViewState: StateFlow = _contactsViewState private val _roomViewState = MutableStateFlow(RoomUiState.None) val roomViewState: StateFlow = _roomViewState + private val addParticipantsViewState = MutableStateFlow(AddParticipantsUiState.None) + val addParticipantsUiState: StateFlow = addParticipantsViewState private val _searchQuery = MutableStateFlow("") val searchQuery: StateFlow = _searchQuery private val shareTypes: MutableList = mutableListOf(ShareType.User.shareType) @@ -32,6 +34,8 @@ class ContactsViewModel @Inject constructor( val searchState: StateFlow = _searchState private val _isAddParticipantsView = MutableStateFlow(false) val isAddParticipantsView: StateFlow = _isAddParticipantsView + private val selectedParticipants = mutableListOf() + val selectedParticipantsList: List = selectedParticipants init { getContactsFromSearchParams() @@ -41,6 +45,9 @@ class ContactsViewModel @Inject constructor( _searchQuery.value = query } + fun updateSelectedParticipants(participants: List) { + selectedParticipants.addAll(participants) + } fun updateSearchState(searchState: Boolean) { _searchState.value = searchState } @@ -89,6 +96,17 @@ class ContactsViewModel @Inject constructor( fun getImageUri(avatarId: String, requestBigSize: Boolean): String { return repository.getImageUri(avatarId, requestBigSize) } + fun addParticipants(conversationToken: String, userId: String, sourceType: String) { + viewModelScope.launch { + try { + val participantsOverall = repository.addParticipants(conversationToken, userId, sourceType) + val participants = participantsOverall.ocs?.data + addParticipantsViewState.value = AddParticipantsUiState.Success(participants) + } catch (exception: Exception) { + addParticipantsViewState.value = AddParticipantsUiState.Error(exception.message ?: "") + } + } + } } sealed class ContactsUiState { @@ -103,3 +121,9 @@ sealed class RoomUiState { data class Success(val conversation: Conversation?) : RoomUiState() data class Error(val message: String) : RoomUiState() } + +sealed class AddParticipantsUiState() { + data object None : AddParticipantsUiState() + data class Success(val participants: List?) : AddParticipantsUiState() + data class Error(val message: String) : AddParticipantsUiState() +} diff --git a/app/src/main/java/com/nextcloud/talk/contacts/ContentItem.kt b/app/src/main/java/com/nextcloud/talk/contacts/ContentItem.kt index 828af63c882..e1cd47940ea 100644 --- a/app/src/main/java/com/nextcloud/talk/contacts/ContentItem.kt +++ b/app/src/main/java/com/nextcloud/talk/contacts/ContentItem.kt @@ -74,7 +74,7 @@ fun ContactsItem(contacts: List, contactsViewModel: ContactsVi } ).toString() } - val selectedContacts = remember { mutableStateListOf() } + val selectedContacts = remember { mutableStateListOf() } LazyColumn( modifier = Modifier .padding(8.dp)