mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-19 19:49:33 +01:00
Start ContactsActivity to edit participants
Signed-off-by: sowjanyakch <sowjanya.kch@gmail.com>
This commit is contained in:
parent
6d0144db1a
commit
6b82d7209f
@ -12,11 +12,15 @@ import android.app.Activity
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Parcelable
|
import android.util.Log
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
@ -26,15 +30,20 @@ import androidx.compose.foundation.layout.padding
|
|||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.layout.wrapContentHeight
|
import androidx.compose.foundation.layout.wrapContentHeight
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||||
import androidx.compose.material.icons.automirrored.filled.List
|
import androidx.compose.material.icons.automirrored.filled.List
|
||||||
import androidx.compose.material.icons.filled.Search
|
import androidx.compose.material.icons.filled.Search
|
||||||
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@ -48,6 +57,7 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.res.vectorResource
|
import androidx.compose.ui.res.vectorResource
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
@ -75,21 +85,28 @@ class ContactsActivityCompose : BaseActivity() {
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
||||||
contactsViewModel = ViewModelProvider(this, viewModelFactory)[ContactsViewModel::class.java]
|
contactsViewModel = ViewModelProvider(this, viewModelFactory)[ContactsViewModel::class.java]
|
||||||
val isAddParticipants = intent.getBooleanExtra("isAddParticipants", false)
|
|
||||||
contactsViewModel.updateIsAddParticipants(isAddParticipants)
|
|
||||||
if (isAddParticipants) {
|
|
||||||
contactsViewModel.updateShareTypes(
|
|
||||||
listOf(
|
|
||||||
ShareType.Group.shareType,
|
|
||||||
ShareType.Email.shareType,
|
|
||||||
ShareType.Circle.shareType
|
|
||||||
)
|
|
||||||
)
|
|
||||||
contactsViewModel.getContactsFromSearchParams()
|
|
||||||
}
|
|
||||||
setContent {
|
setContent {
|
||||||
|
val isAddParticipants = intent.getBooleanExtra("isAddParticipants", false)
|
||||||
|
val isAddParticipantsEdit = intent.getBooleanExtra("isAddParticipantsEdit", false)
|
||||||
|
contactsViewModel.updateIsAddParticipants(isAddParticipants)
|
||||||
|
if (isAddParticipants) {
|
||||||
|
contactsViewModel.updateShareTypes(
|
||||||
|
listOf(
|
||||||
|
ShareType.Group.shareType,
|
||||||
|
ShareType.Email.shareType,
|
||||||
|
ShareType.Circle.shareType
|
||||||
|
)
|
||||||
|
)
|
||||||
|
contactsViewModel.getContactsFromSearchParams()
|
||||||
|
}
|
||||||
val colorScheme = viewThemeUtils.getColorScheme(this)
|
val colorScheme = viewThemeUtils.getColorScheme(this)
|
||||||
val uiState = contactsViewModel.contactsViewState.collectAsState()
|
val uiState = contactsViewModel.contactsViewState.collectAsState()
|
||||||
|
val selectedParticipants: List<AutocompleteUser> = if (isAddParticipantsEdit) {
|
||||||
|
intent.getParcelableArrayListExtra("selectedParticipants") ?: emptyList()
|
||||||
|
} else {
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
contactsViewModel.updateSelectedParticipants(selectedParticipants)
|
||||||
MaterialTheme(
|
MaterialTheme(
|
||||||
colorScheme = colorScheme
|
colorScheme = colorScheme
|
||||||
) {
|
) {
|
||||||
@ -108,7 +125,8 @@ class ContactsActivityCompose : BaseActivity() {
|
|||||||
ContactsList(
|
ContactsList(
|
||||||
contactsUiState = uiState.value,
|
contactsUiState = uiState.value,
|
||||||
contactsViewModel = contactsViewModel,
|
contactsViewModel = contactsViewModel,
|
||||||
context = context
|
context = context,
|
||||||
|
selectedParticipants = selectedParticipants.toMutableList()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,13 +236,17 @@ fun AppBar(title: String, context: Context, contactsViewModel: ContactsViewModel
|
|||||||
Text(
|
Text(
|
||||||
text = stringResource(id = R.string.nc_contacts_done),
|
text = stringResource(id = R.string.nc_contacts_done),
|
||||||
modifier = Modifier.clickable {
|
modifier = Modifier.clickable {
|
||||||
val selectedParticipants: List<AutocompleteUser> = contactsViewModel.selectedParticipantsList
|
val activity = context as? Activity
|
||||||
val intent = Intent(context, ConversationCreationActivity::class.java)
|
val resultIntent = Intent().apply {
|
||||||
intent.putParcelableArrayListExtra(
|
putParcelableArrayListExtra(
|
||||||
"selectedParticipants",
|
"selectedParticipants",
|
||||||
selectedParticipants as ArrayList<Parcelable>
|
contactsViewModel
|
||||||
)
|
.selectedParticipantsList as
|
||||||
context.startActivity(intent)
|
ArrayList<AutocompleteUser>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
activity?.setResult(Activity.RESULT_OK, resultIntent)
|
||||||
|
activity?.finish()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -304,6 +326,98 @@ fun ConversationCreationOptions(context: Context, contactsViewModel: ContactsVie
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ContactsList(
|
||||||
|
contactsUiState: ContactsUiState,
|
||||||
|
contactsViewModel: ContactsViewModel,
|
||||||
|
context: Context,
|
||||||
|
selectedParticipants: MutableList<AutocompleteUser>
|
||||||
|
) {
|
||||||
|
when (contactsUiState) {
|
||||||
|
is ContactsUiState.None -> {
|
||||||
|
}
|
||||||
|
is ContactsUiState.Loading -> {
|
||||||
|
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
|
CircularProgressIndicator()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is ContactsUiState.Success -> {
|
||||||
|
val contacts = contactsUiState.contacts
|
||||||
|
Log.d(CompanionClass.TAG, "Contacts:$contacts")
|
||||||
|
if (contacts != null) {
|
||||||
|
ContactsItem(contacts, contactsViewModel, context, selectedParticipants)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is ContactsUiState.Error -> {
|
||||||
|
val errorMessage = contactsUiState.message
|
||||||
|
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||||
|
Text(text = "Error: $errorMessage", color = Color.Red)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
|
@Composable
|
||||||
|
fun ContactsItem(
|
||||||
|
contacts: List<AutocompleteUser>,
|
||||||
|
contactsViewModel: ContactsViewModel,
|
||||||
|
context: Context,
|
||||||
|
selectedParticipants: MutableList<AutocompleteUser>
|
||||||
|
) {
|
||||||
|
val groupedContacts: Map<String, List<AutocompleteUser>> = contacts.groupBy { contact ->
|
||||||
|
(
|
||||||
|
if (contact.source == "users") {
|
||||||
|
contact.label?.first()?.uppercase()
|
||||||
|
} else {
|
||||||
|
contact.source?.replaceFirstChar { actorType ->
|
||||||
|
actorType.uppercase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).toString()
|
||||||
|
}
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(8.dp)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
contentPadding = PaddingValues(all = 10.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(10.dp)
|
||||||
|
) {
|
||||||
|
groupedContacts.forEach { (initial, contactsForInitial) ->
|
||||||
|
stickyHeader {
|
||||||
|
Column {
|
||||||
|
Surface(Modifier.fillParentMaxWidth()) {
|
||||||
|
Header(initial)
|
||||||
|
}
|
||||||
|
HorizontalDivider(thickness = 0.1.dp, color = Color.Black)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
items(contactsForInitial) { contact ->
|
||||||
|
ContactItemRow(
|
||||||
|
contact = contact,
|
||||||
|
contactsViewModel = contactsViewModel,
|
||||||
|
context = context,
|
||||||
|
selectedContacts = selectedParticipants
|
||||||
|
)
|
||||||
|
Log.d(CompanionClass.TAG, "Contacts:$contact")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun Header(header: String) {
|
||||||
|
Text(
|
||||||
|
text = header,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(Color.Transparent)
|
||||||
|
.padding(start = 60.dp),
|
||||||
|
color = Color.Blue,
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
class CompanionClass {
|
class CompanionClass {
|
||||||
companion object {
|
companion object {
|
||||||
internal val TAG = ContactsActivityCompose::class.simpleName
|
internal val TAG = ContactsActivityCompose::class.simpleName
|
||||||
|
@ -31,7 +31,7 @@ class ContactsViewModel @Inject constructor(
|
|||||||
private val _searchState = MutableStateFlow(false)
|
private val _searchState = MutableStateFlow(false)
|
||||||
val searchState: StateFlow<Boolean> = _searchState
|
val searchState: StateFlow<Boolean> = _searchState
|
||||||
private val selectedParticipants = mutableListOf<AutocompleteUser>()
|
private val selectedParticipants = mutableListOf<AutocompleteUser>()
|
||||||
val selectedParticipantsList: List<AutocompleteUser> = selectedParticipants
|
val selectedParticipantsList: MutableList<AutocompleteUser> = selectedParticipants
|
||||||
private val _isAddParticipantsView = MutableStateFlow(false)
|
private val _isAddParticipantsView = MutableStateFlow(false)
|
||||||
val isAddParticipantsView: StateFlow<Boolean> = _isAddParticipantsView
|
val isAddParticipantsView: StateFlow<Boolean> = _isAddParticipantsView
|
||||||
|
|
||||||
|
@ -1,118 +0,0 @@
|
|||||||
/*
|
|
||||||
* Nextcloud Talk - Android Client
|
|
||||||
*
|
|
||||||
* SPDX-FileCopyrightText: 2024 Your Name <your@email.com>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.nextcloud.talk.contacts
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
|
||||||
import androidx.compose.foundation.lazy.items
|
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
|
||||||
import androidx.compose.material3.HorizontalDivider
|
|
||||||
import androidx.compose.material3.Surface
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.mutableStateListOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun ContactsList(contactsUiState: ContactsUiState, contactsViewModel: ContactsViewModel, context: Context) {
|
|
||||||
when (contactsUiState) {
|
|
||||||
is ContactsUiState.None -> {
|
|
||||||
}
|
|
||||||
is ContactsUiState.Loading -> {
|
|
||||||
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
|
||||||
CircularProgressIndicator()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is ContactsUiState.Success -> {
|
|
||||||
val contacts = contactsUiState.contacts
|
|
||||||
Log.d(CompanionClass.TAG, "Contacts:$contacts")
|
|
||||||
if (contacts != null) {
|
|
||||||
ContactsItem(contacts, contactsViewModel, context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is ContactsUiState.Error -> {
|
|
||||||
val errorMessage = contactsUiState.message
|
|
||||||
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
|
||||||
Text(text = "Error: $errorMessage", color = Color.Red)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
|
||||||
@Composable
|
|
||||||
fun ContactsItem(contacts: List<AutocompleteUser>, contactsViewModel: ContactsViewModel, context: Context) {
|
|
||||||
val groupedContacts: Map<String, List<AutocompleteUser>> = contacts.groupBy { contact ->
|
|
||||||
(
|
|
||||||
if (contact.source == "users") {
|
|
||||||
contact.label?.first()?.uppercase()
|
|
||||||
} else {
|
|
||||||
contact.source?.replaceFirstChar { actorType ->
|
|
||||||
actorType.uppercase()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
).toString()
|
|
||||||
}
|
|
||||||
val selectedContacts = remember { mutableStateListOf<AutocompleteUser>() }
|
|
||||||
LazyColumn(
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(8.dp)
|
|
||||||
.fillMaxWidth(),
|
|
||||||
contentPadding = PaddingValues(all = 10.dp),
|
|
||||||
verticalArrangement = Arrangement.spacedBy(10.dp)
|
|
||||||
) {
|
|
||||||
groupedContacts.forEach { (initial, contactsForInitial) ->
|
|
||||||
stickyHeader {
|
|
||||||
Column {
|
|
||||||
Surface(Modifier.fillParentMaxWidth()) {
|
|
||||||
Header(initial)
|
|
||||||
}
|
|
||||||
HorizontalDivider(thickness = 0.1.dp, color = Color.Black)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
items(contactsForInitial) { contact ->
|
|
||||||
ContactItemRow(
|
|
||||||
contact = contact,
|
|
||||||
contactsViewModel = contactsViewModel,
|
|
||||||
context = context,
|
|
||||||
selectedContacts = selectedContacts
|
|
||||||
)
|
|
||||||
Log.d(CompanionClass.TAG, "Contacts:$contact")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun Header(header: String) {
|
|
||||||
Text(
|
|
||||||
text = header,
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.background(Color.Transparent)
|
|
||||||
.padding(start = 60.dp),
|
|
||||||
color = Color.Blue,
|
|
||||||
fontWeight = FontWeight.Bold
|
|
||||||
)
|
|
||||||
}
|
|
@ -7,24 +7,29 @@
|
|||||||
|
|
||||||
package com.nextcloud.talk.conversationcreation
|
package com.nextcloud.talk.conversationcreation
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import androidx.activity.compose.ManagedActivityResultLauncher
|
||||||
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
|
import androidx.activity.result.ActivityResult
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
@ -56,6 +61,7 @@ import com.nextcloud.talk.R
|
|||||||
import com.nextcloud.talk.activities.BaseActivity
|
import com.nextcloud.talk.activities.BaseActivity
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.contacts.ContactsActivityCompose
|
import com.nextcloud.talk.contacts.ContactsActivityCompose
|
||||||
|
import com.nextcloud.talk.contacts.loadImage
|
||||||
import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser
|
import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -63,60 +69,76 @@ import javax.inject.Inject
|
|||||||
class ConversationCreationActivity : BaseActivity() {
|
class ConversationCreationActivity : BaseActivity() {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var viewModelFactory: ViewModelProvider.Factory
|
lateinit var viewModelFactory: ViewModelProvider.Factory
|
||||||
private lateinit var conversationCreationViewModel: ConversationCreationViewModel
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
|
||||||
conversationCreationViewModel =
|
|
||||||
ViewModelProvider(this, viewModelFactory)[ConversationCreationViewModel::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()
|
|
||||||
|
|
||||||
|
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
||||||
|
val conversationCreationViewModel = ViewModelProvider(
|
||||||
|
this,
|
||||||
|
viewModelFactory
|
||||||
|
)[ConversationCreationViewModel::class.java]
|
||||||
setContent {
|
setContent {
|
||||||
val colorScheme = viewThemeUtils.getColorScheme(this)
|
val colorScheme = viewThemeUtils.getColorScheme(this)
|
||||||
MaterialTheme(
|
MaterialTheme(
|
||||||
colorScheme = colorScheme
|
colorScheme = colorScheme
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
ConversationCreationScreen(conversationCreationViewModel)
|
||||||
Scaffold(
|
|
||||||
topBar = {
|
|
||||||
TopAppBar(
|
|
||||||
title = { Text(text = stringResource(id = R.string.nc_new_conversation)) },
|
|
||||||
navigationIcon = {
|
|
||||||
IconButton(onClick = {
|
|
||||||
(context as? Activity)?.finish()
|
|
||||||
}) {
|
|
||||||
Icon(
|
|
||||||
Icons.AutoMirrored.Filled.ArrowBack,
|
|
||||||
contentDescription = stringResource(R.string.back_button)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
content = {
|
|
||||||
Column(Modifier.padding(it)) {
|
|
||||||
DefaultUserAvatar()
|
|
||||||
UploadAvatar()
|
|
||||||
ConversationNameAndDescription(conversationCreationViewModel)
|
|
||||||
AddParticipants(selectedParticipants, context)
|
|
||||||
RoomCreationOptions(conversationCreationViewModel)
|
|
||||||
CreateConversation()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun ConversationCreationScreen(conversationCreationViewModel: ConversationCreationViewModel) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val launcher = rememberLauncherForActivityResult(
|
||||||
|
contract = ActivityResultContracts.StartActivityForResult(),
|
||||||
|
|
||||||
|
onResult = { result ->
|
||||||
|
if (result.resultCode == Activity.RESULT_OK) {
|
||||||
|
val data = result.data
|
||||||
|
val selectedParticipants = data?.getParcelableArrayListExtra<AutocompleteUser>("selectedParticipants")
|
||||||
|
?: emptyList()
|
||||||
|
conversationCreationViewModel.updateSelectedParticipants(selectedParticipants)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
TopAppBar(
|
||||||
|
title = { Text(text = stringResource(id = R.string.nc_new_conversation)) },
|
||||||
|
navigationIcon = {
|
||||||
|
IconButton(onClick = {
|
||||||
|
(context as? Activity)?.finish()
|
||||||
|
}) {
|
||||||
|
Icon(
|
||||||
|
Icons.AutoMirrored.Filled.ArrowBack,
|
||||||
|
contentDescription = stringResource(id = R.string.back_button)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
content = { paddingValues ->
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(paddingValues)
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
|
DefaultUserAvatar()
|
||||||
|
UploadAvatar()
|
||||||
|
ConversationNameAndDescription(conversationCreationViewModel)
|
||||||
|
AddParticipants(launcher, context, conversationCreationViewModel)
|
||||||
|
RoomCreationOptions(conversationCreationViewModel)
|
||||||
|
CreateConversation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun DefaultUserAvatar() {
|
fun DefaultUserAvatar() {
|
||||||
Box(
|
Box(
|
||||||
@ -196,7 +218,7 @@ fun ConversationNameAndDescription(conversationCreationViewModel: ConversationCr
|
|||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = conversationDescription.value,
|
value = conversationDescription.value,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
conversationCreationViewModel.updateRoomName(it)
|
conversationCreationViewModel.updateConversationDescription(it)
|
||||||
},
|
},
|
||||||
label = { Text(text = stringResource(id = R.string.nc_conversation_description)) },
|
label = { Text(text = stringResource(id = R.string.nc_conversation_description)) },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@ -205,59 +227,88 @@ fun ConversationNameAndDescription(conversationCreationViewModel: ConversationCr
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SuspiciousIndentation")
|
||||||
@Composable
|
@Composable
|
||||||
fun AddParticipants(selectedParticipants: List<AutocompleteUser>?, context: Context) {
|
fun AddParticipants(
|
||||||
Row {
|
launcher: ManagedActivityResultLauncher<Intent, ActivityResult>,
|
||||||
Text(
|
context: Context,
|
||||||
text = stringResource(id = R.string.nc_participants).uppercase(),
|
conversationCreationViewModel: ConversationCreationViewModel
|
||||||
fontSize = 14.sp,
|
) {
|
||||||
modifier = Modifier.padding(top = 24.dp, start = 16.dp, end = 16.dp, bottom = 16.dp)
|
val participants = conversationCreationViewModel.selectedParticipants.collectAsState()
|
||||||
)
|
|
||||||
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(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier.fillMaxHeight()
|
||||||
.padding(start = 16.dp, end = 16.dp)
|
.padding(start = 16.dp, end = 16.dp, top = 16.dp)
|
||||||
.clickable {
|
|
||||||
val intent = Intent(context, ContactsActivityCompose::class.java)
|
|
||||||
intent.putExtra("isAddParticipants", true)
|
|
||||||
context.startActivity(intent)
|
|
||||||
},
|
|
||||||
verticalAlignment = Alignment
|
|
||||||
.CenterVertically
|
|
||||||
) {
|
) {
|
||||||
if (selectedParticipants?.isEmpty() == true) {
|
Row {
|
||||||
Icon(
|
Text(
|
||||||
painter = painterResource(id = R.drawable.ic_account_plus),
|
text = stringResource(id = R.string.nc_participants).uppercase(),
|
||||||
contentDescription = null,
|
fontSize = 14.sp,
|
||||||
modifier = Modifier.size(24.dp)
|
modifier = Modifier.padding(start = 16.dp, bottom = 16.dp)
|
||||||
)
|
)
|
||||||
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
if (participants.value.isNotEmpty()) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.nc_edit),
|
||||||
|
fontSize = 12.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(start = 16.dp, bottom = 16.dp)
|
||||||
|
.clickable {
|
||||||
|
val intent = Intent(context, ContactsActivityCompose::class.java)
|
||||||
|
intent.putParcelableArrayListExtra(
|
||||||
|
"selected participants",
|
||||||
|
participants.value as ArrayList<AutocompleteUser>
|
||||||
|
)
|
||||||
|
intent.putExtra("isAddParticipantsEdit", true)
|
||||||
|
launcher.launch(intent)
|
||||||
|
},
|
||||||
|
textAlign = TextAlign.Right
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Text(text = stringResource(id = R.string.nc_add_participants), modifier = Modifier.padding(start = 16.dp))
|
participants.value.forEach { participant ->
|
||||||
} else {
|
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
|
||||||
LazyColumn {
|
val imageUri = participant.id?.let { conversationCreationViewModel.getImageUri(it, true) }
|
||||||
items(selectedParticipants!!) { participant ->
|
val errorPlaceholderImage: Int = R.drawable.account_circle_96dp
|
||||||
participant.label?.let {
|
val loadedImage = loadImage(imageUri, context, errorPlaceholderImage)
|
||||||
Text(
|
AsyncImage(
|
||||||
text = it,
|
model = loadedImage,
|
||||||
modifier = Modifier.padding(all = 16.dp)
|
contentDescription = stringResource(id = R.string.user_avatar),
|
||||||
)
|
modifier = Modifier.size(width = 32.dp, height = 32.dp)
|
||||||
}
|
)
|
||||||
HorizontalDivider(thickness = 0.1.dp, color = Color.Black)
|
participant.label?.let {
|
||||||
|
Text(
|
||||||
|
text = it,
|
||||||
|
modifier = Modifier.padding(all = 16.dp),
|
||||||
|
fontSize = 15.sp
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
HorizontalDivider(thickness = 0.1.dp, color = Color.Black)
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable {
|
||||||
|
val intent = Intent(context, ContactsActivityCompose::class.java)
|
||||||
|
intent.putExtra("isAddParticipants", true)
|
||||||
|
launcher.launch(intent)
|
||||||
|
},
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
if (participants.value.isEmpty()) {
|
||||||
|
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)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -366,78 +417,3 @@ fun CreateConversation() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// @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
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
@ -14,4 +14,5 @@ interface ConversationCreationRepository {
|
|||||||
suspend fun renameConversation(roomToken: String, roomNameNew: String?): GenericOverall
|
suspend fun renameConversation(roomToken: String, roomNameNew: String?): GenericOverall
|
||||||
suspend fun setConversationDescription(roomToken: String, description: String?): GenericOverall
|
suspend fun setConversationDescription(roomToken: String, description: String?): GenericOverall
|
||||||
suspend fun addParticipants(conversationToken: String?, userId: String, sourceType: String): AddParticipantOverall
|
suspend fun addParticipants(conversationToken: String?, userId: String, sourceType: String): AddParticipantOverall
|
||||||
|
fun getImageUri(avatarId: String, requestBigSize: Boolean): String
|
||||||
}
|
}
|
||||||
|
@ -73,4 +73,12 @@ class ConversationCreationRepositoryImpl(
|
|||||||
}
|
}
|
||||||
return ncApiCoroutines.addParticipant(credentials, retrofitBucket.url, retrofitBucket.queryMap)
|
return ncApiCoroutines.addParticipant(credentials, retrofitBucket.url, retrofitBucket.queryMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getImageUri(avatarId: String, requestBigSize: Boolean): String {
|
||||||
|
return ApiUtils.getUrlForAvatar(
|
||||||
|
_currentUser.baseUrl,
|
||||||
|
avatarId,
|
||||||
|
requestBigSize
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import androidx.compose.runtime.mutableStateOf
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.nextcloud.talk.contacts.AddParticipantsUiState
|
import com.nextcloud.talk.contacts.AddParticipantsUiState
|
||||||
|
import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -20,6 +21,12 @@ import javax.inject.Inject
|
|||||||
class ConversationCreationViewModel @Inject constructor(
|
class ConversationCreationViewModel @Inject constructor(
|
||||||
private val repository: ConversationCreationRepository
|
private val repository: ConversationCreationRepository
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
private val _selectedParticipants = MutableStateFlow<List<AutocompleteUser>>(emptyList())
|
||||||
|
val selectedParticipants: StateFlow<List<AutocompleteUser>> = _selectedParticipants
|
||||||
|
|
||||||
|
fun updateSelectedParticipants(participants: List<AutocompleteUser>) {
|
||||||
|
_selectedParticipants.value = participants
|
||||||
|
}
|
||||||
|
|
||||||
private val _roomName = MutableStateFlow("")
|
private val _roomName = MutableStateFlow("")
|
||||||
val roomName: StateFlow<String> = _roomName
|
val roomName: StateFlow<String> = _roomName
|
||||||
@ -69,4 +76,8 @@ class ConversationCreationViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getImageUri(avatarId: String, requestBigSize: Boolean): String {
|
||||||
|
return repository.getImageUri(avatarId, requestBigSize)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user