Merge pull request #4455 from nextcloud/coroutine_3

Migrate Rxjava to Coroutines
This commit is contained in:
Sowjanya Kota 2024-11-19 11:22:42 +01:00 committed by GitHub
commit 8228f770b9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 237 additions and 292 deletions

View file

@ -118,26 +118,6 @@ public interface NcApi {
@Url String url, @Url String url,
@QueryMap Map<String, String> options); @QueryMap Map<String, String> options);
/*
QueryMap items are as follows:
- "roomName" : "newName"
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room/roomToken
*/
@FormUrlEncoded
@PUT
Observable<GenericOverall> renameRoom(@Header("Authorization") String authorization,
@Url String url,
@Field("roomName") String roomName);
@FormUrlEncoded
@PUT
Observable<GenericOverall> setConversationDescription(@Header("Authorization") String authorization,
@Url String url,
@Field("description") String description);
/* /*
QueryMap items are as follows: QueryMap items are as follows:
- "newParticipant" : "user" - "newParticipant" : "user"
@ -413,12 +393,6 @@ public interface NcApi {
@Url String url, @Url String url,
@Field("level") int level); @Field("level") int level);
@FormUrlEncoded
@PUT
Observable<GenericOverall> setConversationReadOnly(@Header("Authorization") String authorization,
@Url String url,
@Field("state") int state);
@FormUrlEncoded @FormUrlEncoded
@POST @POST
Observable<GenericOverall> createRemoteShare(@Nullable @Header("Authorization") String authorization, Observable<GenericOverall> createRemoteShare(@Nullable @Header("Authorization") String authorization,
@ -492,9 +466,6 @@ public interface NcApi {
@Field("objectId") String objectId, @Field("objectId") String objectId,
@Field("metaData") String metaData); @Field("metaData") String metaData);
@DELETE
Observable<GenericOverall> clearChatHistory(@Header("Authorization") String authorization, @Url String url);
@FormUrlEncoded @FormUrlEncoded
@POST @POST
Observable<GenericOverall> notificationCalls(@Header("Authorization") String authorization, Observable<GenericOverall> notificationCalls(@Header("Authorization") String authorization,

View file

@ -133,11 +133,14 @@ interface NcApiCoroutines {
@Body body: RequestBody @Body body: RequestBody
): GenericOverall ): GenericOverall
@DELETE
suspend fun clearChatHistory(@Header("Authorization") authorization: String, @Url url: String): GenericOverall
@FormUrlEncoded @FormUrlEncoded
@PUT @PUT
suspend fun setPassword2( suspend fun setConversationReadOnly(
@Header("Authorization") authorization: String, @Header("Authorization") authorization: String,
@Url url: String, @Url url: String,
@Field("password") password: String @Field("state") state: Int
): GenericOverall ): GenericOverall
} }

View file

@ -27,7 +27,7 @@ import com.google.android.material.snackbar.Snackbar
import com.nextcloud.android.common.ui.theme.utils.ColorRole import com.nextcloud.android.common.ui.theme.utils.ColorRole
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.conversation.viewmodel.RenameConversationViewModel import com.nextcloud.talk.conversationinfoedit.viewmodel.ConversationInfoEditViewModel
import com.nextcloud.talk.conversationlist.ConversationsListActivity import com.nextcloud.talk.conversationlist.ConversationsListActivity
import com.nextcloud.talk.databinding.DialogRenameConversationBinding import com.nextcloud.talk.databinding.DialogRenameConversationBinding
import com.nextcloud.talk.events.ConversationsListFetchDataEvent import com.nextcloud.talk.events.ConversationsListFetchDataEvent
@ -49,7 +49,7 @@ class RenameConversationDialogFragment : DialogFragment() {
lateinit var eventBus: EventBus lateinit var eventBus: EventBus
private lateinit var binding: DialogRenameConversationBinding private lateinit var binding: DialogRenameConversationBinding
private lateinit var viewModel: RenameConversationViewModel private lateinit var viewModel: ConversationInfoEditViewModel
private var emojiPopup: EmojiPopup? = null private var emojiPopup: EmojiPopup? = null
@ -61,7 +61,7 @@ class RenameConversationDialogFragment : DialogFragment() {
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this) NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
viewModel = ViewModelProvider(this, viewModelFactory)[RenameConversationViewModel::class.java] viewModel = ViewModelProvider(this, viewModelFactory)[ConversationInfoEditViewModel::class.java]
roomToken = arguments?.getString(KEY_ROOM_TOKEN)!! roomToken = arguments?.getString(KEY_ROOM_TOKEN)!!
initialName = arguments?.getString(INITIAL_NAME)!! initialName = arguments?.getString(INITIAL_NAME)!!
} }
@ -102,7 +102,7 @@ class RenameConversationDialogFragment : DialogFragment() {
val positiveButton = (dialog as AlertDialog).getButton(AlertDialog.BUTTON_POSITIVE) val positiveButton = (dialog as AlertDialog).getButton(AlertDialog.BUTTON_POSITIVE)
positiveButton.isEnabled = false positiveButton.isEnabled = false
positiveButton.setOnClickListener { positiveButton.setOnClickListener {
viewModel.renameConversation(roomToken, binding.textEdit.text.toString()) viewModel.renameRoom(roomToken, binding.textEdit.text.toString())
} }
themeDialog() themeDialog()
@ -169,17 +169,21 @@ class RenameConversationDialogFragment : DialogFragment() {
} }
private fun setupStateObserver() { private fun setupStateObserver() {
viewModel.viewState.observe(viewLifecycleOwner) { state -> viewModel.renameRoomUiState.observe(viewLifecycleOwner) { state ->
when (state) { when (state) {
is RenameConversationViewModel.InitialState -> {} is ConversationInfoEditViewModel.RenameRoomUiState.None -> {
is RenameConversationViewModel.RenamingState -> {} }
is RenameConversationViewModel.RenamingSuccessState -> handleSuccess() is ConversationInfoEditViewModel.RenameRoomUiState.Success -> {
is RenameConversationViewModel.RenamingFailedState -> showError() handleSuccess()
else -> {} }
is ConversationInfoEditViewModel.RenameRoomUiState.Error -> {
showError()
}
} }
} }
} }
@SuppressLint("StringFormatInvalid")
private fun handleSuccess() { private fun handleSuccess() {
eventBus.post(ConversationsListFetchDataEvent()) eventBus.post(ConversationsListFetchDataEvent())

View file

@ -8,13 +8,10 @@ package com.nextcloud.talk.conversation.repository
import com.nextcloud.talk.models.json.conversations.ConversationEnums import com.nextcloud.talk.models.json.conversations.ConversationEnums
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 io.reactivex.Observable import io.reactivex.Observable
interface ConversationRepository { interface ConversationRepository {
fun renameConversation(roomToken: String, roomNameNew: String): Observable<GenericOverall>
fun createConversation( fun createConversation(
roomName: String, roomName: String,
conversationType: ConversationEnums.ConversationType? conversationType: ConversationEnums.ConversationType?

View file

@ -11,7 +11,6 @@ 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.json.conversations.ConversationEnums import com.nextcloud.talk.models.json.conversations.ConversationEnums
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.utils.ApiUtils import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
import io.reactivex.Observable import io.reactivex.Observable
@ -24,23 +23,6 @@ class ConversationRepositoryImpl(private val ncApi: NcApi, currentUserProvider:
val currentUser: User = currentUserProvider.currentUser.blockingGet() val currentUser: User = currentUserProvider.currentUser.blockingGet()
val credentials: String = ApiUtils.getCredentials(currentUser.username, currentUser.token)!! val credentials: String = ApiUtils.getCredentials(currentUser.username, currentUser.token)!!
override fun renameConversation(roomToken: String, roomNameNew: String): Observable<GenericOverall> {
val apiVersion = ApiUtils.getConversationApiVersion(currentUser, intArrayOf(ApiUtils.API_V4, ApiUtils.API_V1))
return ncApi.renameRoom(
credentials,
ApiUtils.getUrlForRoom(
apiVersion,
currentUser.baseUrl!!,
roomToken
),
roomNameNew
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retry(API_RETRIES)
}
override fun createConversation( override fun createConversation(
roomName: String, roomName: String,
conversationType: ConversationEnums.ConversationType? conversationType: ConversationEnums.ConversationType?
@ -76,6 +58,5 @@ class ConversationRepositoryImpl(private val ncApi: NcApi, currentUserProvider:
companion object { companion object {
private const val ROOM_TYPE_PUBLIC = "3" private const val ROOM_TYPE_PUBLIC = "3"
private const val ROOM_TYPE_GROUP = "2" private const val ROOM_TYPE_GROUP = "2"
const val API_RETRIES: Long = 3
} }
} }

View file

@ -1,70 +0,0 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2023 Marcel Hibbe <dev@mhibbe.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.nextcloud.talk.conversation.viewmodel
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.nextcloud.talk.conversation.repository.ConversationRepository
import com.nextcloud.talk.models.json.generic.GenericOverall
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import javax.inject.Inject
class RenameConversationViewModel @Inject constructor(private val repository: ConversationRepository) : ViewModel() {
sealed class ViewState
object InitialState : ViewState()
object RenamingState : ViewState()
object RenamingSuccessState : ViewState()
object RenamingFailedState : ViewState()
private val _viewState: MutableLiveData<ViewState> = MutableLiveData(
InitialState
)
val viewState: LiveData<ViewState>
get() = _viewState
fun renameConversation(roomToken: String, roomNameNew: String) {
_viewState.value = RenamingState
repository.renameConversation(
roomToken,
roomNameNew
)
.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.subscribe(RenameConversationObserver())
}
inner class RenameConversationObserver : Observer<GenericOverall> {
lateinit var genericOverall: GenericOverall
override fun onSubscribe(d: Disposable) = Unit
override fun onNext(response: GenericOverall) {
genericOverall = response
}
override fun onError(e: Throwable) {
Log.e(TAG, "Failed to rename conversation", e)
_viewState.value = RenamingFailedState
}
override fun onComplete() {
_viewState.value = RenamingSuccessState
}
}
companion object {
private val TAG = RenameConversationViewModel::class.java.simpleName
}
}

View file

@ -260,12 +260,30 @@ class ConversationInfoActivity :
viewModel.getConversationReadOnlyState.observe(this) { state -> viewModel.getConversationReadOnlyState.observe(this) { state ->
when (state) { when (state) {
is ConversationInfoViewModel.SetConversationReadOnlySuccessState -> { is ConversationInfoViewModel.SetConversationReadOnlyViewState.Success -> {
} }
is ConversationInfoViewModel.SetConversationReadOnlyErrorState -> { is ConversationInfoViewModel.SetConversationReadOnlyViewState.Error -> {
Snackbar.make(binding.root, R.string.conversation_read_only_failed, Snackbar.LENGTH_LONG).show() Snackbar.make(binding.root, R.string.conversation_read_only_failed, Snackbar.LENGTH_LONG).show()
} }
else -> { is ConversationInfoViewModel.SetConversationReadOnlyViewState.None -> {
}
}
}
viewModel.clearChatHistoryViewState.observe(this) { uiState ->
when (uiState) {
is ConversationInfoViewModel.ClearChatHistoryViewState.None -> {
}
is ConversationInfoViewModel.ClearChatHistoryViewState.Success -> {
Snackbar.make(
binding.root,
context.getString(R.string.nc_clear_history_success),
Snackbar.LENGTH_LONG
).show()
}
is ConversationInfoViewModel.ClearChatHistoryViewState.Error -> {
Snackbar.make(binding.root, R.string.nc_common_error_sorry, Snackbar.LENGTH_LONG).show()
Log.e(TAG, "failed to clear chat history", uiState.exception)
} }
} }
} }
@ -670,7 +688,6 @@ class ConversationInfoActivity :
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(intent) startActivity(intent)
} }
WorkInfo.State.FAILED -> { WorkInfo.State.FAILED -> {
val errorType = workInfo.outputData.getString("error_type") val errorType = workInfo.outputData.getString("error_type")
if (errorType == LeaveConversationWorker.ERROR_NO_OTHER_MODERATORS_OR_OWNERS_LEFT) { if (errorType == LeaveConversationWorker.ERROR_NO_OTHER_MODERATORS_OR_OWNERS_LEFT) {
@ -687,7 +704,6 @@ class ConversationInfoActivity :
).show() ).show()
} }
} }
else -> { else -> {
} }
} }
@ -726,35 +742,7 @@ class ConversationInfoActivity :
private fun clearHistory() { private fun clearHistory() {
val apiVersion = ApiUtils.getChatApiVersion(spreedCapabilities, intArrayOf(1)) val apiVersion = ApiUtils.getChatApiVersion(spreedCapabilities, intArrayOf(1))
viewModel.clearChatHistory(apiVersion, conversationToken)
ncApi.clearChatHistory(
credentials,
ApiUtils.getUrlForChat(apiVersion, conversationUser.baseUrl!!, conversationToken)
)
?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.subscribe(object : Observer<GenericOverall> {
override fun onSubscribe(d: Disposable) {
// unused atm
}
override fun onNext(genericOverall: GenericOverall) {
Snackbar.make(
binding.root,
context.getString(R.string.nc_clear_history_success),
Snackbar.LENGTH_LONG
).show()
}
override fun onError(e: Throwable) {
Snackbar.make(binding.root, R.string.nc_common_error_sorry, Snackbar.LENGTH_LONG).show()
Log.e(TAG, "failed to clear chat history", e)
}
override fun onComplete() {
// unused atm
}
})
} }
private fun deleteConversation() { private fun deleteConversation() {
@ -849,7 +837,7 @@ class ConversationInfoActivity :
binding.lockConversationSwitch.isChecked = !isLocked binding.lockConversationSwitch.isChecked = !isLocked
databaseStorageModule!!.saveBoolean("lock_switch", !isLocked) databaseStorageModule!!.saveBoolean("lock_switch", !isLocked)
val state = if (isLocked) 0 else 1 val state = if (isLocked) 0 else 1
makeConversationReadOnly(conversationUser, conversationToken, state) makeConversationReadOnly(conversationToken, state)
} }
} else { } else {
binding.lockConversation.visibility = GONE binding.lockConversation.visibility = GONE
@ -929,8 +917,8 @@ class ConversationInfoActivity :
} }
} }
private fun makeConversationReadOnly(conversationUser: User, roomToken: String, state: Int) { private fun makeConversationReadOnly(roomToken: String, state: Int) {
viewModel.setConversationReadOnly(conversationUser, roomToken, state) viewModel.setConversationReadOnly(roomToken, state)
} }
private fun initRecordingConsentOption() { private fun initRecordingConsentOption() {

View file

@ -79,13 +79,6 @@ class ConversationInfoViewModel @Inject constructor(
val getUnBanActorState: LiveData<ViewState> val getUnBanActorState: LiveData<ViewState>
get() = _getUnBanActorState get() = _getUnBanActorState
object SetConversationReadOnlySuccessState : ViewState
object SetConversationReadOnlyErrorState : ViewState
private val _getConversationReadOnlyState: MutableLiveData<ViewState> = MutableLiveData()
val getConversationReadOnlyState: LiveData<ViewState>
get() = _getConversationReadOnlyState
object GetRoomStartState : ViewState object GetRoomStartState : ViewState
object GetRoomErrorState : ViewState object GetRoomErrorState : ViewState
open class GetRoomSuccessState(val conversationModel: ConversationModel) : ViewState open class GetRoomSuccessState(val conversationModel: ConversationModel) : ViewState
@ -110,6 +103,16 @@ class ConversationInfoViewModel @Inject constructor(
val getCapabilitiesViewState: LiveData<ViewState> val getCapabilitiesViewState: LiveData<ViewState>
get() = _getCapabilitiesViewState get() = _getCapabilitiesViewState
private val _clearChatHistoryViewState: MutableLiveData<ClearChatHistoryViewState> =
MutableLiveData(ClearChatHistoryViewState.None)
val clearChatHistoryViewState: LiveData<ClearChatHistoryViewState>
get() = _clearChatHistoryViewState
private val _getConversationReadOnlyState: MutableLiveData<SetConversationReadOnlyViewState> =
MutableLiveData(SetConversationReadOnlyViewState.None)
val getConversationReadOnlyState: LiveData<SetConversationReadOnlyViewState>
get() = _getConversationReadOnlyState
fun getRoom(user: User, token: String) { fun getRoom(user: User, token: String) {
_viewState.value = GetRoomStartState _viewState.value = GetRoomStartState
chatNetworkDataSource.getRoom(user, token) chatNetworkDataSource.getRoom(user, token)
@ -196,28 +199,15 @@ class ConversationInfoViewModel @Inject constructor(
}) })
} }
fun setConversationReadOnly(user: User, token: String, state: Int) { fun setConversationReadOnly(roomToken: String, state: Int) {
val apiVersion = ApiUtils.getConversationApiVersion(user, intArrayOf(ApiUtils.API_V4, ApiUtils.API_V1)) viewModelScope.launch {
val url = ApiUtils.getUrlForConversationReadOnly(apiVersion, user.baseUrl!!, token) try {
conversationsRepository.setConversationReadOnly(user.getCredentials(), url, state) conversationsRepository.setConversationReadOnly(roomToken, state)
.subscribeOn(Schedulers.io()) _getConversationReadOnlyState.value = SetConversationReadOnlyViewState.Success
?.observeOn(AndroidSchedulers.mainThread()) } catch (exception: Exception) {
?.subscribe(object : Observer<GenericOverall> { _getConversationReadOnlyState.value = SetConversationReadOnlyViewState.Error(exception)
override fun onSubscribe(p0: Disposable) { }
} }
override fun onError(error: Throwable) {
_getConversationReadOnlyState.value = SetConversationReadOnlyErrorState
}
override fun onComplete() {
// unused atm
}
override fun onNext(p0: GenericOverall) {
_getConversationReadOnlyState.value = SetConversationReadOnlySuccessState
}
})
} }
fun unbanActor(user: User, token: String, banId: Int) { fun unbanActor(user: User, token: String, banId: Int) {
@ -279,6 +269,17 @@ class ConversationInfoViewModel @Inject constructor(
conversationsRepository.unarchiveConversation(user.getCredentials(), url) conversationsRepository.unarchiveConversation(user.getCredentials(), url)
} }
fun clearChatHistory(apiVersion: Int, roomToken: String) {
viewModelScope.launch {
try {
conversationsRepository.clearChatHistory(apiVersion, roomToken)
_clearChatHistoryViewState.value = ClearChatHistoryViewState.Success
} catch (exception: Exception) {
_clearChatHistoryViewState.value = ClearChatHistoryViewState.Error(exception)
}
}
}
inner class GetRoomObserver : Observer<ConversationModel> { inner class GetRoomObserver : Observer<ConversationModel> {
override fun onSubscribe(d: Disposable) { override fun onSubscribe(d: Disposable) {
// unused atm // unused atm
@ -302,6 +303,18 @@ class ConversationInfoViewModel @Inject constructor(
private val TAG = ConversationInfoViewModel::class.simpleName private val TAG = ConversationInfoViewModel::class.simpleName
} }
sealed class ClearChatHistoryViewState {
data object None : ClearChatHistoryViewState()
data object Success : ClearChatHistoryViewState()
data class Error(val exception: Exception) : ClearChatHistoryViewState()
}
sealed class SetConversationReadOnlyViewState {
data object None : SetConversationReadOnlyViewState()
data object Success : SetConversationReadOnlyViewState()
data class Error(val exception: Exception) : SetConversationReadOnlyViewState()
}
sealed class AllowGuestsUIState { sealed class AllowGuestsUIState {
data object None : AllowGuestsUIState() data object None : AllowGuestsUIState()
data class Success(val allow: Boolean) : AllowGuestsUIState() data class Success(val allow: Boolean) : AllowGuestsUIState()

View file

@ -36,15 +36,10 @@ import com.nextcloud.talk.extensions.loadUserAvatar
import com.nextcloud.talk.models.domain.ConversationModel import com.nextcloud.talk.models.domain.ConversationModel
import com.nextcloud.talk.models.json.capabilities.SpreedCapability import com.nextcloud.talk.models.json.capabilities.SpreedCapability
import com.nextcloud.talk.models.json.conversations.ConversationEnums import com.nextcloud.talk.models.json.conversations.ConversationEnums
import com.nextcloud.talk.models.json.generic.GenericOverall
import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.CapabilitiesUtil import com.nextcloud.talk.utils.CapabilitiesUtil
import com.nextcloud.talk.utils.PickImage import com.nextcloud.talk.utils.PickImage
import com.nextcloud.talk.utils.bundle.BundleKeys import com.nextcloud.talk.utils.bundle.BundleKeys
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.io.File import java.io.File
import javax.inject.Inject import javax.inject.Inject
@ -172,6 +167,45 @@ class ConversationInfoEditActivity : BaseActivity() {
else -> {} else -> {}
} }
} }
conversationInfoEditViewModel.renameRoomUiState.observe(this) { uiState ->
when (uiState) {
is ConversationInfoEditViewModel.RenameRoomUiState.None -> {
}
is ConversationInfoEditViewModel.RenameRoomUiState.Success -> {
if (CapabilitiesUtil.isConversationDescriptionEndpointAvailable(spreedCapabilities)) {
saveConversationDescription()
} else {
finish()
}
}
is ConversationInfoEditViewModel.RenameRoomUiState.Error -> {
Snackbar.make(
binding.root,
context.getString(R.string.default_error_msg),
Snackbar.LENGTH_LONG
).show()
Log.e(TAG, "Error while saving conversation name", uiState.exception)
}
}
}
conversationInfoEditViewModel.setConversationDescriptionUiState.observe(this) { uiState ->
when (uiState) {
is ConversationInfoEditViewModel.SetConversationDescriptionUiState.None -> {
}
is ConversationInfoEditViewModel.SetConversationDescriptionUiState.Success -> {
finish()
}
is ConversationInfoEditViewModel.SetConversationDescriptionUiState.Error -> {
Snackbar.make(
binding.root,
context.getString(R.string.default_error_msg),
Snackbar.LENGTH_LONG
).show()
Log.e(TAG, "Error while saving conversation description", uiState.exception)
}
}
}
} }
private fun setupAvatarOptions() { private fun setupAvatarOptions() {
@ -236,87 +270,16 @@ class ConversationInfoEditActivity : BaseActivity() {
} }
private fun saveConversationNameAndDescription() { private fun saveConversationNameAndDescription() {
val apiVersion = val newRoomName = binding.conversationName.text.toString()
ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(ApiUtils.API_V4, ApiUtils.API_V1)) conversationInfoEditViewModel.renameRoom(
conversation!!.token,
ncApi.renameRoom( newRoomName
credentials,
ApiUtils.getUrlForRoom(
apiVersion,
conversationUser.baseUrl!!,
conversation!!.token
),
binding.conversationName.text.toString()
) )
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retry(1)
.subscribe(object : Observer<GenericOverall> {
override fun onSubscribe(d: Disposable) {
// unused atm
}
override fun onNext(genericOverall: GenericOverall) {
if (CapabilitiesUtil.isConversationDescriptionEndpointAvailable(spreedCapabilities)) {
saveConversationDescription()
} else {
finish()
}
}
override fun onError(e: Throwable) {
Snackbar.make(
binding.root,
context.getString(R.string.default_error_msg),
Snackbar.LENGTH_LONG
).show()
Log.e(TAG, "Error while saving conversation name", e)
}
override fun onComplete() {
// unused atm
}
})
} }
fun saveConversationDescription() { fun saveConversationDescription() {
val apiVersion = val conversationDescription = binding.conversationDescription.text.toString()
ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(ApiUtils.API_V4, ApiUtils.API_V1)) conversationInfoEditViewModel.setConversationDescription(conversation!!.token, conversationDescription)
ncApi.setConversationDescription(
credentials,
ApiUtils.getUrlForConversationDescription(
apiVersion,
conversationUser.baseUrl!!,
conversation!!.token
),
binding.conversationDescription.text.toString()
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retry(1)
.subscribe(object : Observer<GenericOverall> {
override fun onSubscribe(d: Disposable) {
// unused atm
}
override fun onNext(genericOverall: GenericOverall) {
finish()
}
override fun onError(e: Throwable) {
Snackbar.make(
binding.root,
context.getString(R.string.default_error_msg),
Snackbar.LENGTH_LONG
).show()
Log.e(TAG, "Error while saving conversation description", e)
}
override fun onComplete() {
// unused atm
}
})
} }
private fun handleResult(result: ActivityResult, onResult: (result: ActivityResult) -> Unit) { private fun handleResult(result: ActivityResult, onResult: (result: ActivityResult) -> Unit) {

View file

@ -8,6 +8,7 @@ package com.nextcloud.talk.conversationinfoedit.data
import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.models.domain.ConversationModel import com.nextcloud.talk.models.domain.ConversationModel
import com.nextcloud.talk.models.json.generic.GenericOverall
import io.reactivex.Observable import io.reactivex.Observable
import java.io.File import java.io.File
@ -16,4 +17,8 @@ interface ConversationInfoEditRepository {
fun uploadConversationAvatar(user: User, file: File, roomToken: String): Observable<ConversationModel> fun uploadConversationAvatar(user: User, file: File, roomToken: String): Observable<ConversationModel>
fun deleteConversationAvatar(user: User, roomToken: String): Observable<ConversationModel> fun deleteConversationAvatar(user: User, roomToken: String): Observable<ConversationModel>
suspend fun renameConversation(roomToken: String, roomNameNew: String): GenericOverall
suspend fun setConversationDescription(roomToken: String, conversationDescription: String?): GenericOverall
} }

View file

@ -7,8 +7,10 @@
package com.nextcloud.talk.conversationinfoedit.data package com.nextcloud.talk.conversationinfoedit.data
import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.api.NcApi
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.domain.ConversationModel import com.nextcloud.talk.models.domain.ConversationModel
import com.nextcloud.talk.models.json.generic.GenericOverall
import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.Mimetype import com.nextcloud.talk.utils.Mimetype
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
@ -18,7 +20,11 @@ import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.asRequestBody import okhttp3.RequestBody.Companion.asRequestBody
import java.io.File import java.io.File
class ConversationInfoEditRepositoryImpl(private val ncApi: NcApi, currentUserProvider: CurrentUserProviderNew) : class ConversationInfoEditRepositoryImpl(
private val ncApi: NcApi,
private val ncApiCoroutines: NcApiCoroutines,
currentUserProvider: CurrentUserProviderNew
) :
ConversationInfoEditRepository { ConversationInfoEditRepository {
val currentUser: User = currentUserProvider.currentUser.blockingGet() val currentUser: User = currentUserProvider.currentUser.blockingGet()
@ -53,4 +59,33 @@ class ConversationInfoEditRepositoryImpl(private val ncApi: NcApi, currentUserPr
ApiUtils.getUrlForConversationAvatar(1, user.baseUrl!!, roomToken) ApiUtils.getUrlForConversationAvatar(1, user.baseUrl!!, roomToken)
).map { ConversationModel.mapToConversationModel(it.ocs?.data!!, user) } ).map { ConversationModel.mapToConversationModel(it.ocs?.data!!, user) }
} }
override suspend fun renameConversation(roomToken: String, newRoomName: String): GenericOverall {
val apiVersion = ApiUtils.getConversationApiVersion(currentUser, intArrayOf(ApiUtils.API_V4, ApiUtils.API_V1))
return ncApiCoroutines.renameRoom(
credentials,
ApiUtils.getUrlForRoom(
apiVersion,
currentUser.baseUrl!!,
roomToken
),
newRoomName
)
}
override suspend fun setConversationDescription(
roomToken: String,
conversationDescription: String?
): GenericOverall {
return ncApiCoroutines.setConversationDescription(
credentials,
ApiUtils.getUrlForConversationDescription(
apiVersion,
currentUser.baseUrl!!,
roomToken
),
conversationDescription
)
}
} }

View file

@ -10,6 +10,7 @@ import android.util.Log
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.nextcloud.talk.chat.data.network.ChatNetworkDataSource import com.nextcloud.talk.chat.data.network.ChatNetworkDataSource
import com.nextcloud.talk.conversationinfoedit.data.ConversationInfoEditRepository import com.nextcloud.talk.conversationinfoedit.data.ConversationInfoEditRepository
import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.data.user.model.User
@ -18,6 +19,7 @@ import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.launch
import java.io.File import java.io.File
import javax.inject.Inject import javax.inject.Inject
@ -42,6 +44,15 @@ class ConversationInfoEditViewModel @Inject constructor(
val viewState: LiveData<ViewState> val viewState: LiveData<ViewState>
get() = _viewState get() = _viewState
private val _renameRoomUiState = MutableLiveData<RenameRoomUiState>(RenameRoomUiState.None)
val renameRoomUiState: LiveData<RenameRoomUiState>
get() = _renameRoomUiState
private val _setConversationDescriptionUiState =
MutableLiveData<SetConversationDescriptionUiState>(SetConversationDescriptionUiState.None)
val setConversationDescriptionUiState: LiveData<SetConversationDescriptionUiState>
get() = _setConversationDescriptionUiState
fun getRoom(user: User, token: String) { fun getRoom(user: User, token: String) {
_viewState.value = GetRoomStartState _viewState.value = GetRoomStartState
repository.getRoom(user, token) repository.getRoom(user, token)
@ -64,6 +75,32 @@ class ConversationInfoEditViewModel @Inject constructor(
?.subscribe(DeleteConversationAvatarObserver()) ?.subscribe(DeleteConversationAvatarObserver())
} }
fun renameRoom(roomToken: String, newRoomName: String) {
viewModelScope.launch {
try {
conversationInfoEditRepository.renameConversation(roomToken, newRoomName)
_renameRoomUiState.value = RenameRoomUiState.Success
} catch (exception: Exception) {
_renameRoomUiState.value = RenameRoomUiState.Error(exception)
}
}
}
fun setConversationDescription(roomToken: String, conversationDescription: String?) {
viewModelScope.launch {
try {
conversationInfoEditRepository.setConversationDescription(
roomToken,
conversationDescription
)
_setConversationDescriptionUiState.value = SetConversationDescriptionUiState.Success
} catch (exception: Exception) {
_setConversationDescriptionUiState.value = SetConversationDescriptionUiState.Error(exception)
}
}
}
inner class GetRoomObserver : Observer<ConversationModel> { inner class GetRoomObserver : Observer<ConversationModel> {
override fun onSubscribe(d: Disposable) { override fun onSubscribe(d: Disposable) {
// unused atm // unused atm
@ -124,4 +161,16 @@ class ConversationInfoEditViewModel @Inject constructor(
companion object { companion object {
private val TAG = ConversationInfoEditViewModel::class.simpleName private val TAG = ConversationInfoEditViewModel::class.simpleName
} }
sealed class RenameRoomUiState {
data object None : RenameRoomUiState()
data object Success : RenameRoomUiState()
data class Error(val exception: Exception) : RenameRoomUiState()
}
sealed class SetConversationDescriptionUiState {
data object None : SetConversationDescriptionUiState()
data object Success : SetConversationDescriptionUiState()
data class Error(val exception: Exception) : SetConversationDescriptionUiState()
}
} }

View file

@ -159,9 +159,10 @@ class RepositoryModule {
@Provides @Provides
fun provideConversationInfoEditRepository( fun provideConversationInfoEditRepository(
ncApi: NcApi, ncApi: NcApi,
ncApiCoroutines: NcApiCoroutines,
userProvider: CurrentUserProviderNew userProvider: CurrentUserProviderNew
): ConversationInfoEditRepository { ): ConversationInfoEditRepository {
return ConversationInfoEditRepositoryImpl(ncApi, userProvider) return ConversationInfoEditRepositoryImpl(ncApi, ncApiCoroutines, userProvider)
} }
@Provides @Provides

View file

@ -13,7 +13,6 @@ import com.nextcloud.talk.chat.viewmodels.ChatViewModel
import com.nextcloud.talk.contacts.ContactsViewModel import com.nextcloud.talk.contacts.ContactsViewModel
import com.nextcloud.talk.chat.viewmodels.MessageInputViewModel import com.nextcloud.talk.chat.viewmodels.MessageInputViewModel
import com.nextcloud.talk.conversation.viewmodel.ConversationViewModel import com.nextcloud.talk.conversation.viewmodel.ConversationViewModel
import com.nextcloud.talk.conversation.viewmodel.RenameConversationViewModel
import com.nextcloud.talk.conversationcreation.ConversationCreationViewModel import com.nextcloud.talk.conversationcreation.ConversationCreationViewModel
import com.nextcloud.talk.conversationinfo.viewmodel.ConversationInfoViewModel import com.nextcloud.talk.conversationinfo.viewmodel.ConversationInfoViewModel
import com.nextcloud.talk.conversationinfoedit.viewmodel.ConversationInfoEditViewModel import com.nextcloud.talk.conversationinfoedit.viewmodel.ConversationInfoEditViewModel
@ -138,11 +137,6 @@ abstract class ViewModelModule {
@ViewModelKey(ConversationInfoEditViewModel::class) @ViewModelKey(ConversationInfoEditViewModel::class)
abstract fun conversationInfoEditViewModel(viewModel: ConversationInfoEditViewModel): ViewModel abstract fun conversationInfoEditViewModel(viewModel: ConversationInfoEditViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(RenameConversationViewModel::class)
abstract fun renameConversationViewModel(viewModel: RenameConversationViewModel): ViewModel
@Binds @Binds
@IntoMap @IntoMap
@ViewModelKey(ConversationViewModel::class) @ViewModelKey(ConversationViewModel::class)

View file

@ -25,5 +25,7 @@ interface ConversationsRepository {
suspend fun setPassword(password: String, token: String): GenericOverall suspend fun setPassword(password: String, token: String): GenericOverall
fun setConversationReadOnly(credentials: String, url: String, state: Int): Observable<GenericOverall> suspend fun setConversationReadOnly(roomToken: String, state: Int): GenericOverall
suspend fun clearChatHistory(apiVersion: Int, roomToken: String): GenericOverall
} }

View file

@ -74,8 +74,10 @@ class ConversationsRepositoryImpl(
return coroutineApi.unarchiveConversation(credentials, url) return coroutineApi.unarchiveConversation(credentials, url)
} }
override fun setConversationReadOnly(credentials: String, url: String, state: Int): Observable<GenericOverall> { override suspend fun setConversationReadOnly(roomToken: String, state: Int): GenericOverall {
return api.setConversationReadOnly(credentials, url, state) val apiVersion = ApiUtils.getConversationApiVersion(user, intArrayOf(ApiUtils.API_V4, ApiUtils.API_V1))
val url = ApiUtils.getUrlForConversationReadOnly(apiVersion, user.baseUrl!!, roomToken)
return coroutineApi.setConversationReadOnly(credentials, url, state)
} }
override suspend fun setPassword(password: String, token: String): GenericOverall { override suspend fun setPassword(password: String, token: String): GenericOverall {
@ -91,6 +93,13 @@ class ConversationsRepositoryImpl(
return result return result
} }
override suspend fun clearChatHistory(apiVersion: Int, roomToken: String): GenericOverall {
return coroutineApi.clearChatHistory(
credentials,
ApiUtils.getUrlForChat(apiVersion, user.baseUrl!!, roomToken)
)
}
private fun apiVersion(): Int { private fun apiVersion(): Int {
return ApiUtils.getConversationApiVersion(user, intArrayOf(ApiUtils.API_V4)) return ApiUtils.getConversationApiVersion(user, intArrayOf(ApiUtils.API_V4))
} }