add participants list

Signed-off-by: sowjanyakch <sowjanya.kch@gmail.com>
This commit is contained in:
sowjanyakch 2024-08-16 23:31:12 +02:00 committed by Marcel Hibbe
parent 6a01309f2f
commit 6d0144db1a
No known key found for this signature in database
GPG Key ID: C793F8B59F43CE7B
10 changed files with 211 additions and 97 deletions

View File

@ -12,7 +12,7 @@ import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.os.Parcelable
import androidx.activity.compose.setContent
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
@ -127,12 +127,12 @@ fun ContactItemRow(
) {
val isSelected = contact in selectedContacts
val roomUiState by contactsViewModel.roomViewState.collectAsState()
val isAddParticipants = contactsViewModel.isAddParticipantsView.value
val isAddParticipants = contactsViewModel.isAddParticipantsView.collectAsState()
Row(
modifier = Modifier
.fillMaxWidth()
.clickable {
if (!isAddParticipants) {
if (!isAddParticipants.value) {
contactsViewModel.createRoom(
CompanionClass.ROOM_TYPE_ONE_ONE,
contact.source!!,
@ -159,7 +159,7 @@ fun ContactItemRow(
modifier = Modifier.size(width = 45.dp, height = 45.dp)
)
Text(modifier = Modifier.padding(16.dp), text = contact.label!!)
if (isAddParticipants) {
if (isAddParticipants.value) {
if (isSelected) {
Spacer(modifier = Modifier.weight(1f))
Icon(
@ -176,7 +176,6 @@ fun ContactItemRow(
val conversation = (roomUiState as RoomUiState.Success).conversation
val bundle = Bundle()
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, conversation?.token)
// bundle.putString(BundleKeys.KEY_ROOM_ID, conversation?.roomId)
val chatIntent = Intent(context, ChatActivity::class.java)
chatIntent.putExtras(bundle)
chatIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
@ -198,8 +197,7 @@ fun ContactItemRow(
fun AppBar(title: String, context: Context, contactsViewModel: ContactsViewModel) {
val searchQuery by contactsViewModel.searchQuery.collectAsState()
val searchState = contactsViewModel.searchState.collectAsState()
val addParticipantsUiState = contactsViewModel.addParticipantsUiState.collectAsState()
val conversationToken:String? = null
val isAddParticipants = contactsViewModel.isAddParticipantsView.collectAsState()
TopAppBar(
title = { Text(text = title) },
@ -216,42 +214,22 @@ fun AppBar(title: String, context: Context, contactsViewModel: ContactsViewModel
}) {
Icon(Icons.Filled.Search, contentDescription = stringResource(R.string.search_icon))
}
if (contactsViewModel.isAddParticipantsView.value) {
if (isAddParticipants.value) {
Text(
text = stringResource(id = R.string.nc_contacts_done),
modifier = Modifier.clickable {
for(contacts in contactsViewModel.selectedParticipantsList){
contacts.let { contact ->
contactsViewModel.addParticipants(
conversationToken,
contact.id!!,
contact.source!!
)
}
}
val selectedParticipants: List<AutocompleteUser> = contactsViewModel.selectedParticipantsList
val intent = Intent(context, ConversationCreationActivity::class.java)
intent.putParcelableArrayListExtra(
"selectedParticipants",
selectedParticipants as ArrayList<Parcelable>
)
context.startActivity(intent)
}
)
}
}
)
val state = addParticipantsUiState.value
when(state){
is AddParticipantsUiState.Error -> {
val errorMessage = state.message
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Text(text = "Error: $errorMessage", color = Color.Red)
}
}
is AddParticipantsUiState.None -> {
}
is AddParticipantsUiState.Success -> {
val conversation = state.participants
Log.d("ContactsActivityCompose", "$conversation")
}
}
if (searchState.value) {
Row {
DisplaySearch(

View File

@ -9,11 +9,9 @@ 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<String>): 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
}

View File

@ -12,11 +12,8 @@ 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(
@ -75,28 +72,4 @@ 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)
}
}

View File

@ -24,18 +24,16 @@ class ContactsViewModel @Inject constructor(
val contactsViewState: StateFlow<ContactsUiState> = _contactsViewState
private val _roomViewState = MutableStateFlow<RoomUiState>(RoomUiState.None)
val roomViewState: StateFlow<RoomUiState> = _roomViewState
private val addParticipantsViewState = MutableStateFlow<AddParticipantsUiState>(AddParticipantsUiState.None)
val addParticipantsUiState: StateFlow<AddParticipantsUiState> = addParticipantsViewState
private val _searchQuery = MutableStateFlow("")
val searchQuery: StateFlow<String> = _searchQuery
private val shareTypes: MutableList<String> = mutableListOf(ShareType.User.shareType)
val shareTypeList: List<String> = shareTypes
private val _searchState = MutableStateFlow(false)
val searchState: StateFlow<Boolean> = _searchState
private val _isAddParticipantsView = MutableStateFlow(false)
val isAddParticipantsView: StateFlow<Boolean> = _isAddParticipantsView
private val selectedParticipants = mutableListOf<AutocompleteUser>()
val selectedParticipantsList: List<AutocompleteUser> = selectedParticipants
private val _isAddParticipantsView = MutableStateFlow(false)
val isAddParticipantsView: StateFlow<Boolean> = _isAddParticipantsView
init {
getContactsFromSearchParams()
@ -75,7 +73,6 @@ class ContactsViewModel @Inject constructor(
}
}
}
fun createRoom(roomType: String, sourceType: String, userId: String, conversationName: String?) {
viewModelScope.launch {
try {
@ -96,17 +93,6 @@ 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 {

View File

@ -10,6 +10,7 @@ package com.nextcloud.talk.conversationcreation
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.compose.foundation.clickable
@ -22,9 +23,13 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
@ -37,9 +42,11 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.ViewModelProvider
@ -49,7 +56,7 @@ import com.nextcloud.talk.R
import com.nextcloud.talk.activities.BaseActivity
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.contacts.ContactsActivityCompose
import com.nextcloud.talk.contacts.ContactsViewModel
import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser
import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class)
@ -64,7 +71,13 @@ class ConversationCreationActivity : BaseActivity() {
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
conversationCreationViewModel =
ViewModelProvider(this, viewModelFactory)[ConversationCreationViewModel::class.java]
val contactsViewModel = ViewModelProvider(this, viewModelFactory)[ContactsViewModel::class.java]
val selectedParticipants: List<AutocompleteUser>? = when (
Build.VERSION.SDK_INT >= Build.VERSION_CODES
.TIRAMISU
) {
true -> intent.getParcelableArrayListExtra("selectedParticipants")
else -> intent.extras?.getParcelableArrayList("selectedParticipants")
} ?: emptyList()
setContent {
val colorScheme = viewThemeUtils.getColorScheme(this)
@ -93,8 +106,9 @@ class ConversationCreationActivity : BaseActivity() {
DefaultUserAvatar()
UploadAvatar()
ConversationNameAndDescription(conversationCreationViewModel)
AddParticipants(contactsViewModel, context)
AddParticipants(selectedParticipants, context)
RoomCreationOptions(conversationCreationViewModel)
CreateConversation()
}
}
)
@ -192,12 +206,26 @@ fun ConversationNameAndDescription(conversationCreationViewModel: ConversationCr
}
@Composable
fun AddParticipants(contactsViewModel: ContactsViewModel, context: Context) {
Text(
text = stringResource(id = R.string.nc_participants).uppercase(),
fontSize = 14.sp,
modifier = Modifier.padding(top = 24.dp, start = 16.dp, end = 16.dp, bottom = 16.dp)
)
fun AddParticipants(selectedParticipants: List<AutocompleteUser>?, context: Context) {
Row {
Text(
text = stringResource(id = R.string.nc_participants).uppercase(),
fontSize = 14.sp,
modifier = Modifier.padding(top = 24.dp, start = 16.dp, end = 16.dp, bottom = 16.dp)
)
if (selectedParticipants?.isNotEmpty() == true) {
Text(
text = stringResource(id = R.string.nc_edit),
fontSize = 12.sp,
modifier = Modifier.padding(top = 24.dp, start = 16.dp, end = 16.dp, bottom = 16.dp)
.clickable {
val intent = Intent(context, ContactsActivityCompose::class.java)
context.startActivity(intent)
},
textAlign = TextAlign.Right
)
}
}
Row(
modifier = Modifier
@ -210,13 +238,27 @@ fun AddParticipants(contactsViewModel: ContactsViewModel, context: Context) {
verticalAlignment = Alignment
.CenterVertically
) {
Icon(
painter = painterResource(id = R.drawable.ic_account_plus),
contentDescription = null,
modifier = Modifier.size(24.dp)
)
if (selectedParticipants?.isEmpty() == true) {
Icon(
painter = painterResource(id = R.drawable.ic_account_plus),
contentDescription = null,
modifier = Modifier.size(24.dp)
)
Text(text = stringResource(id = R.string.nc_add_participants), modifier = Modifier.padding(start = 16.dp))
Text(text = stringResource(id = R.string.nc_add_participants), modifier = Modifier.padding(start = 16.dp))
} else {
LazyColumn {
items(selectedParticipants!!) { participant ->
participant.label?.let {
Text(
text = it,
modifier = Modifier.padding(all = 16.dp)
)
}
HorizontalDivider(thickness = 0.1.dp, color = Color.Black)
}
}
}
}
}
@ -307,3 +349,95 @@ fun ConversationOptions(icon: Int? = null, text: Int, switch: @Composable (() ->
switch?.invoke()
}
}
@Composable
fun CreateConversation() {
Box(
modifier = Modifier
.fillMaxWidth()
.padding(all = 16.dp),
contentAlignment = Alignment.Center
) {
Button(
onClick = {
}
) {
Text(text = stringResource(id = R.string.create_conversation))
}
}
}
//
// @SuppressLint("UnrememberedMutableState")
// @OptIn(ExperimentalMaterial3Api::class)
// @Composable
// fun AppBar(title: String, context: Context, contactsViewModel: ContactsViewModel) {
// val searchQuery by contactsViewModel.searchQuery.collectAsState()
// val searchState = contactsViewModel.searchState.collectAsState()
// val addParticipantsUiState = contactsViewModel.addParticipantsUiState.collectAsState()
// val conversationToken:String? = null
//
// TopAppBar(
// title = { Text(text = title) },
// navigationIcon = {
// IconButton(onClick = {
// (context as? Activity)?.finish()
// }) {
// Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = stringResource(R.string.back_button))
// }
// },
// actions = {
// IconButton(onClick = {
// contactsViewModel.updateSearchState(true)
// }) {
// Icon(Icons.Filled.Search, contentDescription = stringResource(R.string.search_icon))
// }
// if (contactsViewModel.isAddParticipantsView.value) {
// Text(
// text = stringResource(id = R.string.nc_contacts_done),
// modifier = Modifier.clickable {
// for(contacts in contactsViewModel.selectedParticipantsList){
// contacts.let { contact ->
// contactsViewModel.addParticipants(
// conversationToken,
// contact.id!!,
// contact.source!!
// )
// }
// }
// }
// )
// }
// }
// )
// val state = addParticipantsUiState.value
// when(state){
// is AddParticipantsUiState.Error -> {
// val errorMessage = state.message
// Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
// Text(text = "Error: $errorMessage", color = Color.Red)
// }
//
// }
// is AddParticipantsUiState.None -> {
//
//
// }
// is AddParticipantsUiState.Success -> {
// val conversation = state.participants
// Log.d("ContactsActivityCompose", "$conversation")
// }
// }
// if (searchState.value) {
// Row {
// DisplaySearch(
// text = searchQuery,
// onTextChange = { searchQuery ->
// contactsViewModel.updateSearchQuery(query = searchQuery)
// contactsViewModel.getContactsFromSearchParams()
// },
// contactsViewModel = contactsViewModel
// )
// }
// }
// }

View File

@ -8,8 +8,10 @@
package com.nextcloud.talk.conversationcreation
import com.nextcloud.talk.models.json.generic.GenericOverall
import com.nextcloud.talk.models.json.participants.AddParticipantOverall
interface ConversationCreationRepository {
suspend fun renameConversation(roomToken: String, roomNameNew: String?): GenericOverall
suspend fun setConversationDescription(roomToken: String, description: String?): GenericOverall
suspend fun addParticipants(conversationToken: String?, userId: String, sourceType: String): AddParticipantOverall
}

View File

@ -9,9 +9,13 @@ package com.nextcloud.talk.conversationcreation
import com.nextcloud.talk.api.NcApiCoroutines
import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.models.RetrofitBucket
import com.nextcloud.talk.models.json.generic.GenericOverall
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
class ConversationCreationRepositoryImpl(
private val ncApiCoroutines: NcApiCoroutines,
@ -45,4 +49,28 @@ class ConversationCreationRepositoryImpl(
description
)
}
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)
}
}

View File

@ -11,6 +11,7 @@ import android.util.Log
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.nextcloud.talk.contacts.AddParticipantsUiState
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
@ -28,6 +29,9 @@ class ConversationCreationViewModel @Inject constructor(
var isConversationAvailableForRegisteredUsers = mutableStateOf(false)
var openForGuestAppUsers = mutableStateOf(false)
private val addParticipantsViewState = MutableStateFlow<AddParticipantsUiState>(AddParticipantsUiState.None)
val addParticipantsUiState: StateFlow<AddParticipantsUiState> = addParticipantsViewState
fun updateRoomName(roomName: String) {
_roomName.value = roomName
}
@ -54,4 +58,15 @@ class ConversationCreationViewModel @Inject constructor(
}
}
}
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 ?: "")
}
}
}
}

View File

@ -79,7 +79,6 @@ import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.arbitrarystorage.ArbitraryStorageManager
import com.nextcloud.talk.chat.ChatActivity
import com.nextcloud.talk.contacts.ContactsActivity
import com.nextcloud.talk.contacts.ContactsActivityCompose
import com.nextcloud.talk.conversationlist.viewmodels.ConversationsListViewModel
import com.nextcloud.talk.data.network.NetworkMonitor
@ -1067,7 +1066,7 @@ class ConversationsListActivity :
conversation.type === ConversationEnums.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL
private fun showNewConversationsScreen() {
val intent = Intent(context, ContactsActivity::class.java)
val intent = Intent(context, ContactsActivityCompose::class.java)
intent.putExtra(KEY_NEW_CONVERSATION, true)
startActivity(intent)
}

View File

@ -567,6 +567,7 @@ How to translate with transifex:
<string name="no_phone_book_integration_due_to_permissions">No phone number integration due to missing permissions</string>
<string name="nc_phone_book_integration_chat_via">Chat via %s</string>
<string name="nc_phone_book_integration_account_not_found">Account not found</string>
<string name= "nc_edit">Edit</string>
<!-- save feature -->
<string name="nc_save_message">Save</string>