mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-19 11:39:42 +01:00
Merge pull request #4196 from nextcloud/user_avatar_selection
User avatar selection
This commit is contained in:
commit
946aa60409
@ -15,7 +15,7 @@ import com.github.spotbugs.snom.SpotBugsTask
|
|||||||
plugins {
|
plugins {
|
||||||
id "org.jetbrains.kotlin.plugin.compose" version "2.0.20"
|
id "org.jetbrains.kotlin.plugin.compose" version "2.0.20"
|
||||||
id "org.jetbrains.kotlin.kapt"
|
id "org.jetbrains.kotlin.kapt"
|
||||||
id 'com.google.devtools.ksp' version '2.0.20-1.0.25'
|
id 'com.google.devtools.ksp' version '2.0.20-1.0.24'
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
@ -11,13 +11,16 @@ import com.nextcloud.talk.models.json.autocomplete.AutocompleteOverall
|
|||||||
import com.nextcloud.talk.models.json.conversations.RoomOverall
|
import com.nextcloud.talk.models.json.conversations.RoomOverall
|
||||||
import com.nextcloud.talk.models.json.generic.GenericOverall
|
import com.nextcloud.talk.models.json.generic.GenericOverall
|
||||||
import com.nextcloud.talk.models.json.participants.AddParticipantOverall
|
import com.nextcloud.talk.models.json.participants.AddParticipantOverall
|
||||||
|
import okhttp3.MultipartBody
|
||||||
import retrofit2.http.DELETE
|
import retrofit2.http.DELETE
|
||||||
import retrofit2.http.Field
|
import retrofit2.http.Field
|
||||||
import retrofit2.http.FormUrlEncoded
|
import retrofit2.http.FormUrlEncoded
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
import retrofit2.http.Header
|
import retrofit2.http.Header
|
||||||
|
import retrofit2.http.Multipart
|
||||||
import retrofit2.http.POST
|
import retrofit2.http.POST
|
||||||
import retrofit2.http.PUT
|
import retrofit2.http.PUT
|
||||||
|
import retrofit2.http.Part
|
||||||
import retrofit2.http.Query
|
import retrofit2.http.Query
|
||||||
import retrofit2.http.QueryMap
|
import retrofit2.http.QueryMap
|
||||||
import retrofit2.http.Url
|
import retrofit2.http.Url
|
||||||
@ -96,4 +99,15 @@ interface NcApiCoroutines {
|
|||||||
@Url url: String?,
|
@Url url: String?,
|
||||||
@Field("password") password: String?
|
@Field("password") password: String?
|
||||||
): GenericOverall
|
): GenericOverall
|
||||||
|
|
||||||
|
@Multipart
|
||||||
|
@POST
|
||||||
|
suspend fun uploadConversationAvatar(
|
||||||
|
@Header("Authorization") authorization: String,
|
||||||
|
@Url url: String,
|
||||||
|
@Part attachment: MultipartBody.Part
|
||||||
|
): RoomOverall
|
||||||
|
|
||||||
|
@DELETE
|
||||||
|
suspend fun deleteConversationAvatar(@Header("Authorization") authorization: String, @Url url: String): RoomOverall
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ 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.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.compose.ManagedActivityResultLauncher
|
import androidx.activity.compose.ManagedActivityResultLauncher
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
@ -32,6 +33,7 @@ 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.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.verticalScroll
|
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
|
||||||
@ -57,7 +59,9 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalView
|
import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.compose.ui.res.colorResource
|
import androidx.compose.ui.res.colorResource
|
||||||
@ -77,6 +81,7 @@ import com.nextcloud.talk.chat.ChatActivity
|
|||||||
import com.nextcloud.talk.contacts.ContactsActivityCompose
|
import com.nextcloud.talk.contacts.ContactsActivityCompose
|
||||||
import com.nextcloud.talk.contacts.loadImage
|
import com.nextcloud.talk.contacts.loadImage
|
||||||
import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser
|
import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser
|
||||||
|
import com.nextcloud.talk.utils.PickImage
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys
|
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -84,7 +89,7 @@ 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 pickImage: PickImage
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
@ -93,13 +98,16 @@ class ConversationCreationActivity : BaseActivity() {
|
|||||||
this,
|
this,
|
||||||
viewModelFactory
|
viewModelFactory
|
||||||
)[ConversationCreationViewModel::class.java]
|
)[ConversationCreationViewModel::class.java]
|
||||||
|
val conversationUser = conversationCreationViewModel.currentUser
|
||||||
|
pickImage = PickImage(this, conversationUser)
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
val colorScheme = viewThemeUtils.getColorScheme(this)
|
val colorScheme = viewThemeUtils.getColorScheme(this)
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
MaterialTheme(
|
MaterialTheme(
|
||||||
colorScheme = colorScheme
|
colorScheme = colorScheme
|
||||||
) {
|
) {
|
||||||
ConversationCreationScreen(conversationCreationViewModel, context)
|
ConversationCreationScreen(conversationCreationViewModel, context, pickImage)
|
||||||
}
|
}
|
||||||
SetStatusBarColor()
|
SetStatusBarColor()
|
||||||
}
|
}
|
||||||
@ -125,14 +133,46 @@ private fun SetStatusBarColor() {
|
|||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun ConversationCreationScreen(conversationCreationViewModel: ConversationCreationViewModel, context: Context) {
|
fun ConversationCreationScreen(
|
||||||
|
conversationCreationViewModel: ConversationCreationViewModel,
|
||||||
|
context: Context,
|
||||||
|
pickImage: PickImage
|
||||||
|
) {
|
||||||
|
var selectedImageUri by remember { mutableStateOf<Uri?>(null) }
|
||||||
|
|
||||||
|
val imagePickerLauncher = rememberLauncherForActivityResult(
|
||||||
|
contract = ActivityResultContracts.StartActivityForResult()
|
||||||
|
) { result ->
|
||||||
|
if (result.resultCode == Activity.RESULT_OK) {
|
||||||
|
pickImage.onImagePickerResult(result.data) { uri ->
|
||||||
|
selectedImageUri = uri
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val remoteFilePickerLauncher = rememberLauncherForActivityResult(
|
||||||
|
contract = ActivityResultContracts.StartActivityForResult()
|
||||||
|
) { result ->
|
||||||
|
if (result.resultCode == Activity.RESULT_OK) {
|
||||||
|
pickImage.onSelectRemoteFilesResult(imagePickerLauncher, result.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val cameraLauncher = rememberLauncherForActivityResult(
|
||||||
|
contract = ActivityResultContracts.StartActivityForResult()
|
||||||
|
) { result ->
|
||||||
|
if (result.resultCode == Activity.RESULT_OK) {
|
||||||
|
pickImage.onTakePictureResult(imagePickerLauncher, result.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val launcher = rememberLauncherForActivityResult(
|
val launcher = rememberLauncherForActivityResult(
|
||||||
contract = ActivityResultContracts.StartActivityForResult(),
|
contract = ActivityResultContracts.StartActivityForResult(),
|
||||||
|
|
||||||
onResult = { result ->
|
onResult = { result ->
|
||||||
if (result.resultCode == Activity.RESULT_OK) {
|
if (result.resultCode == Activity.RESULT_OK) {
|
||||||
val data = result.data
|
val data = result.data
|
||||||
val selectedParticipants = data?.getParcelableArrayListExtra<AutocompleteUser>("selectedParticipants")
|
val selectedParticipants =
|
||||||
|
data?.getParcelableArrayListExtra<AutocompleteUser>("selectedParticipants")
|
||||||
?: emptyList()
|
?: emptyList()
|
||||||
val participants = selectedParticipants.toMutableList()
|
val participants = selectedParticipants.toMutableList()
|
||||||
conversationCreationViewModel.updateSelectedParticipants(participants)
|
conversationCreationViewModel.updateSelectedParticipants(participants)
|
||||||
@ -162,43 +202,75 @@ fun ConversationCreationScreen(conversationCreationViewModel: ConversationCreati
|
|||||||
.padding(paddingValues)
|
.padding(paddingValues)
|
||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
) {
|
) {
|
||||||
DefaultUserAvatar()
|
DefaultUserAvatar(selectedImageUri)
|
||||||
UploadAvatar()
|
UploadAvatar(
|
||||||
|
pickImage = pickImage,
|
||||||
|
onImageSelected = { uri -> selectedImageUri = uri },
|
||||||
|
imagePickerLauncher = imagePickerLauncher,
|
||||||
|
remoteFilePickerLauncher = remoteFilePickerLauncher,
|
||||||
|
cameraLauncher = cameraLauncher,
|
||||||
|
onDeleteImage = { selectedImageUri = null }
|
||||||
|
)
|
||||||
|
|
||||||
ConversationNameAndDescription(conversationCreationViewModel)
|
ConversationNameAndDescription(conversationCreationViewModel)
|
||||||
AddParticipants(launcher, context, conversationCreationViewModel)
|
AddParticipants(launcher, context, conversationCreationViewModel)
|
||||||
RoomCreationOptions(conversationCreationViewModel)
|
RoomCreationOptions(conversationCreationViewModel)
|
||||||
CreateConversation(conversationCreationViewModel, context)
|
CreateConversation(conversationCreationViewModel, context, selectedImageUri)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun DefaultUserAvatar() {
|
fun DefaultUserAvatar(selectedImageUri: Uri?) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
|
if (selectedImageUri != null) {
|
||||||
|
AsyncImage(
|
||||||
|
model = selectedImageUri,
|
||||||
|
contentDescription = stringResource(id = R.string.user_avatar),
|
||||||
|
contentScale = ContentScale.Crop,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(84.dp)
|
||||||
|
.padding(top = 8.dp)
|
||||||
|
.clip(CircleShape)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
AsyncImage(
|
AsyncImage(
|
||||||
model = R.drawable.ic_circular_group,
|
model = R.drawable.ic_circular_group,
|
||||||
contentDescription = stringResource(id = R.string.user_avatar),
|
contentDescription = stringResource(id = R.string.user_avatar),
|
||||||
|
contentScale = ContentScale.Crop,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(width = 84.dp, height = 84.dp)
|
.size(84.dp)
|
||||||
.padding(top = 8.dp)
|
.padding(top = 8.dp)
|
||||||
|
.clip(CircleShape)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UploadAvatar() {
|
fun UploadAvatar(
|
||||||
|
pickImage: PickImage,
|
||||||
|
onImageSelected: (Uri) -> Unit,
|
||||||
|
imagePickerLauncher: ManagedActivityResultLauncher<Intent, ActivityResult>,
|
||||||
|
remoteFilePickerLauncher: ManagedActivityResultLauncher<Intent, ActivityResult>,
|
||||||
|
cameraLauncher: ManagedActivityResultLauncher<Intent, ActivityResult>,
|
||||||
|
onDeleteImage: () -> Unit
|
||||||
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(16.dp),
|
.padding(16.dp),
|
||||||
horizontalArrangement = Arrangement.Center
|
horizontalArrangement = Arrangement.Center
|
||||||
) {
|
) {
|
||||||
IconButton(onClick = {
|
IconButton(
|
||||||
}) {
|
onClick = {
|
||||||
|
pickImage.takePicture(cameraLauncher)
|
||||||
|
}
|
||||||
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
painter = painterResource(id = R.drawable.ic_baseline_photo_camera_24),
|
painter = painterResource(id = R.drawable.ic_baseline_photo_camera_24),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
@ -207,24 +279,28 @@ fun UploadAvatar() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
IconButton(onClick = {
|
IconButton(onClick = {
|
||||||
|
pickImage.selectLocal(imagePickerLauncher)
|
||||||
}) {
|
}) {
|
||||||
Icon(
|
Icon(
|
||||||
painter = painterResource(id = R.drawable.ic_folder_multiple_image),
|
painter = painterResource(id = R.drawable.upload),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
modifier = Modifier.size(24.dp)
|
modifier = Modifier.size(24.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
IconButton(
|
||||||
IconButton(onClick = {
|
onClick = {
|
||||||
}) {
|
pickImage.selectRemote(remoteFilePickerLauncher)
|
||||||
Icon(
|
}
|
||||||
painter = painterResource(id = R.drawable.baseline_tag_faces_24),
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = R.drawable.ic_mimetype_folder),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
modifier = Modifier.size(24.dp)
|
modifier = Modifier.size(24.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
IconButton(onClick = {
|
IconButton(onClick = {
|
||||||
|
onDeleteImage()
|
||||||
}) {
|
}) {
|
||||||
Icon(
|
Icon(
|
||||||
painter = painterResource(id = R.drawable.ic_delete_grey600_24dp),
|
painter = painterResource(id = R.drawable.ic_delete_grey600_24dp),
|
||||||
@ -502,7 +578,11 @@ fun ShowPasswordDialog(onDismiss: () -> Unit, conversationCreationViewModel: Con
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CreateConversation(conversationCreationViewModel: ConversationCreationViewModel, context: Context) {
|
fun CreateConversation(
|
||||||
|
conversationCreationViewModel: ConversationCreationViewModel,
|
||||||
|
context: Context,
|
||||||
|
selectedImageUri: Uri?
|
||||||
|
) {
|
||||||
val selectedParticipants by conversationCreationViewModel.selectedParticipants.collectAsState()
|
val selectedParticipants by conversationCreationViewModel.selectedParticipants.collectAsState()
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@ -515,7 +595,8 @@ fun CreateConversation(conversationCreationViewModel: ConversationCreationViewMo
|
|||||||
conversationCreationViewModel.createRoomAndAddParticipants(
|
conversationCreationViewModel.createRoomAndAddParticipants(
|
||||||
roomType = CompanionClass.ROOM_TYPE_GROUP,
|
roomType = CompanionClass.ROOM_TYPE_GROUP,
|
||||||
conversationName = conversationCreationViewModel.roomName.value,
|
conversationName = conversationCreationViewModel.roomName.value,
|
||||||
participants = selectedParticipants.toSet()
|
participants = selectedParticipants.toSet(),
|
||||||
|
selectedImageUri = selectedImageUri
|
||||||
) { roomToken ->
|
) { roomToken ->
|
||||||
val bundle = Bundle()
|
val bundle = Bundle()
|
||||||
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomToken)
|
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomToken)
|
||||||
@ -530,6 +611,7 @@ fun CreateConversation(conversationCreationViewModel: ConversationCreationViewMo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CompanionClass {
|
class CompanionClass {
|
||||||
companion object {
|
companion object {
|
||||||
internal val TAG = ConversationCreationActivity::class.simpleName
|
internal val TAG = ConversationCreationActivity::class.simpleName
|
||||||
|
@ -7,9 +7,11 @@
|
|||||||
|
|
||||||
package com.nextcloud.talk.conversationcreation
|
package com.nextcloud.talk.conversationcreation
|
||||||
|
|
||||||
|
import com.nextcloud.talk.models.domain.ConversationModel
|
||||||
import com.nextcloud.talk.models.json.conversations.RoomOverall
|
import com.nextcloud.talk.models.json.conversations.RoomOverall
|
||||||
import com.nextcloud.talk.models.json.generic.GenericOverall
|
import com.nextcloud.talk.models.json.generic.GenericOverall
|
||||||
import com.nextcloud.talk.models.json.participants.AddParticipantOverall
|
import com.nextcloud.talk.models.json.participants.AddParticipantOverall
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
interface ConversationCreationRepository {
|
interface ConversationCreationRepository {
|
||||||
|
|
||||||
@ -21,4 +23,6 @@ interface ConversationCreationRepository {
|
|||||||
suspend fun createRoom(roomType: String, conversationName: String?): RoomOverall
|
suspend fun createRoom(roomType: String, conversationName: String?): RoomOverall
|
||||||
fun getImageUri(avatarId: String, requestBigSize: Boolean): String
|
fun getImageUri(avatarId: String, requestBigSize: Boolean): String
|
||||||
suspend fun setPassword(roomToken: String, password: String): GenericOverall
|
suspend fun setPassword(roomToken: String, password: String): GenericOverall
|
||||||
|
suspend fun uploadConversationAvatar(file: File, roomToken: String): ConversationModel
|
||||||
|
suspend fun deleteConversationAvatar(roomToken: String): ConversationModel
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ package com.nextcloud.talk.conversationcreation
|
|||||||
import com.nextcloud.talk.api.NcApiCoroutines
|
import com.nextcloud.talk.api.NcApiCoroutines
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.models.RetrofitBucket
|
import com.nextcloud.talk.models.RetrofitBucket
|
||||||
|
import com.nextcloud.talk.models.domain.ConversationModel
|
||||||
import com.nextcloud.talk.models.json.conversations.RoomOverall
|
import com.nextcloud.talk.models.json.conversations.RoomOverall
|
||||||
import com.nextcloud.talk.models.json.generic.GenericOverall
|
import com.nextcloud.talk.models.json.generic.GenericOverall
|
||||||
import com.nextcloud.talk.models.json.participants.AddParticipantOverall
|
import com.nextcloud.talk.models.json.participants.AddParticipantOverall
|
||||||
@ -17,6 +18,11 @@ import com.nextcloud.talk.users.UserManager
|
|||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import com.nextcloud.talk.utils.ApiUtils.getRetrofitBucketForAddParticipant
|
import com.nextcloud.talk.utils.ApiUtils.getRetrofitBucketForAddParticipant
|
||||||
import com.nextcloud.talk.utils.ApiUtils.getRetrofitBucketForAddParticipantWithSource
|
import com.nextcloud.talk.utils.ApiUtils.getRetrofitBucketForAddParticipantWithSource
|
||||||
|
import com.nextcloud.talk.utils.Mimetype
|
||||||
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
|
import okhttp3.MultipartBody
|
||||||
|
import okhttp3.RequestBody.Companion.asRequestBody
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
class ConversationCreationRepositoryImpl(
|
class ConversationCreationRepositoryImpl(
|
||||||
private val ncApiCoroutines: NcApiCoroutines,
|
private val ncApiCoroutines: NcApiCoroutines,
|
||||||
@ -126,6 +132,33 @@ class ConversationCreationRepositoryImpl(
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun uploadConversationAvatar(file: File, roomToken: String): ConversationModel {
|
||||||
|
val builder = MultipartBody.Builder()
|
||||||
|
builder.setType(MultipartBody.FORM)
|
||||||
|
builder.addFormDataPart(
|
||||||
|
"file",
|
||||||
|
file.name,
|
||||||
|
file.asRequestBody(Mimetype.IMAGE_PREFIX_GENERIC.toMediaTypeOrNull())
|
||||||
|
)
|
||||||
|
val filePart: MultipartBody.Part = MultipartBody.Part.createFormData(
|
||||||
|
"file",
|
||||||
|
file.name,
|
||||||
|
file.asRequestBody(Mimetype.IMAGE_JPG.toMediaTypeOrNull())
|
||||||
|
)
|
||||||
|
val response = ncApiCoroutines.uploadConversationAvatar(
|
||||||
|
credentials!!,
|
||||||
|
ApiUtils.getUrlForConversationAvatar(1, _currentUser.baseUrl!!, roomToken),
|
||||||
|
filePart
|
||||||
|
)
|
||||||
|
return ConversationModel.mapToConversationModel(response.ocs?.data!!, _currentUser)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun deleteConversationAvatar(roomToken: String): ConversationModel {
|
||||||
|
val url = ApiUtils.getUrlForConversationAvatar(1, _currentUser.baseUrl!!, roomToken)
|
||||||
|
val response = ncApiCoroutines.deleteConversationAvatar(credentials!!, url)
|
||||||
|
return ConversationModel.mapToConversationModel(response.ocs?.data!!, _currentUser)
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun allowGuests(token: String, allow: Boolean): GenericOverall {
|
override suspend fun allowGuests(token: String, allow: Boolean): GenericOverall {
|
||||||
val url = ApiUtils.getUrlForRoomPublic(
|
val url = ApiUtils.getUrlForRoomPublic(
|
||||||
apiVersion,
|
apiVersion,
|
||||||
|
@ -7,26 +7,34 @@
|
|||||||
|
|
||||||
package com.nextcloud.talk.conversationcreation
|
package com.nextcloud.talk.conversationcreation
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.core.net.toFile
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
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.autocomplete.AutocompleteUser
|
||||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||||
import com.nextcloud.talk.models.json.generic.GenericMeta
|
import com.nextcloud.talk.models.json.generic.GenericMeta
|
||||||
import com.nextcloud.talk.repositories.conversations.ConversationsRepositoryImpl.Companion.STATUS_CODE_OK
|
import com.nextcloud.talk.repositories.conversations.ConversationsRepositoryImpl.Companion.STATUS_CODE_OK
|
||||||
|
import com.nextcloud.talk.users.UserManager
|
||||||
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
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class ConversationCreationViewModel @Inject constructor(
|
class ConversationCreationViewModel @Inject constructor(
|
||||||
private val repository: ConversationCreationRepository
|
private val repository: ConversationCreationRepository,
|
||||||
|
private val userManager: UserManager
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
private val _selectedParticipants = MutableStateFlow<List<AutocompleteUser>>(emptyList())
|
private val _selectedParticipants = MutableStateFlow<List<AutocompleteUser>>(emptyList())
|
||||||
val selectedParticipants: StateFlow<List<AutocompleteUser>> = _selectedParticipants
|
val selectedParticipants: StateFlow<List<AutocompleteUser>> = _selectedParticipants
|
||||||
private val roomViewState = MutableStateFlow<RoomUIState>(RoomUIState.None)
|
private val roomViewState = MutableStateFlow<RoomUIState>(RoomUIState.None)
|
||||||
|
|
||||||
|
private val _currentUser = userManager.currentUser.blockingGet()
|
||||||
|
val currentUser: User = _currentUser
|
||||||
|
|
||||||
fun updateSelectedParticipants(participants: List<AutocompleteUser>) {
|
fun updateSelectedParticipants(participants: List<AutocompleteUser>) {
|
||||||
_selectedParticipants.value = participants
|
_selectedParticipants.value = participants
|
||||||
}
|
}
|
||||||
@ -58,6 +66,7 @@ class ConversationCreationViewModel @Inject constructor(
|
|||||||
roomType: String,
|
roomType: String,
|
||||||
conversationName: String,
|
conversationName: String,
|
||||||
participants: Set<AutocompleteUser>,
|
participants: Set<AutocompleteUser>,
|
||||||
|
selectedImageUri: Uri?,
|
||||||
onRoomCreated: (String) -> Unit
|
onRoomCreated: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
val scope = when {
|
val scope = when {
|
||||||
@ -100,6 +109,9 @@ class ConversationCreationViewModel @Inject constructor(
|
|||||||
repository.setPassword(token, _password.value)
|
repository.setPassword(token, _password.value)
|
||||||
}
|
}
|
||||||
repository.openConversation(token, scope)
|
repository.openConversation(token, scope)
|
||||||
|
if (selectedImageUri != null) {
|
||||||
|
repository.uploadConversationAvatar(selectedImageUri.toFile(), token)
|
||||||
|
}
|
||||||
onRoomCreated(token)
|
onRoomCreated(token)
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
allowGuestsResult.value = AllowGuestsUiState.Error(exception.message ?: "")
|
allowGuestsResult.value = AllowGuestsUiState.Error(exception.message ?: "")
|
||||||
|
Loading…
Reference in New Issue
Block a user