mirror of
https://github.com/nextcloud/talk-android.git
synced 2024-11-23 21:45:42 +03:00
Merge pull request #4446 from nextcloud/coroutine_2
Migrate Rxjava to coroutines #2
This commit is contained in:
commit
b748080360
8 changed files with 135 additions and 149 deletions
|
@ -195,18 +195,6 @@ public interface NcApi {
|
|||
@DELETE
|
||||
Observable<GenericOverall> removeSelfFromRoom(@Header("Authorization") String authorization, @Url String url);
|
||||
|
||||
/*
|
||||
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room/roomToken/public
|
||||
*/
|
||||
@POST
|
||||
Observable<GenericOverall> makeRoomPublic(@Header("Authorization") String authorization, @Url String url);
|
||||
|
||||
/*
|
||||
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /room/roomToken/public
|
||||
*/
|
||||
@DELETE
|
||||
Observable<GenericOverall> makeRoomPrivate(@Header("Authorization") String authorization, @Url String url);
|
||||
|
||||
@DELETE
|
||||
Observable<GenericOverall> deleteRoom(@Header("Authorization") String authorization, @Url String url);
|
||||
|
||||
|
@ -341,18 +329,6 @@ public interface NcApi {
|
|||
Observable<Void> unregisterDeviceForNotificationsWithProxy(@Url String url,
|
||||
@QueryMap Map<String, String> fields);
|
||||
|
||||
@FormUrlEncoded
|
||||
@PUT
|
||||
Observable<GenericOverall> setPassword(@Header("Authorization") String authorization,
|
||||
@Url String url,
|
||||
@Field("password") String password);
|
||||
|
||||
@FormUrlEncoded
|
||||
@PUT
|
||||
Observable<Response<GenericOverall>> setPassword2(@Header("Authorization") String authorization,
|
||||
@Url String url,
|
||||
@Field("password") String password);
|
||||
|
||||
@GET
|
||||
Observable<CapabilitiesOverall> getCapabilities(@Header("Authorization") String authorization, @Url String url);
|
||||
|
||||
|
|
|
@ -89,10 +89,10 @@ interface NcApiCoroutines {
|
|||
): AddParticipantOverall
|
||||
|
||||
@POST
|
||||
suspend fun makeRoomPublic(@Header("Authorization") authorization: String?, @Url url: String): GenericOverall
|
||||
suspend fun makeRoomPublic(@Header("Authorization") authorization: String, @Url url: String): GenericOverall
|
||||
|
||||
@DELETE
|
||||
suspend fun makeRoomPrivate(@Header("Authorization") authorization: String?, @Url url: String): GenericOverall
|
||||
suspend fun makeRoomPrivate(@Header("Authorization") authorization: String, @Url url: String): GenericOverall
|
||||
|
||||
@FormUrlEncoded
|
||||
@PUT
|
||||
|
@ -132,4 +132,12 @@ interface NcApiCoroutines {
|
|||
@Url url: String,
|
||||
@Body body: RequestBody
|
||||
): GenericOverall
|
||||
|
||||
@FormUrlEncoded
|
||||
@PUT
|
||||
suspend fun setPassword2(
|
||||
@Header("Authorization") authorization: String,
|
||||
@Url url: String,
|
||||
@Field("password") password: String
|
||||
): GenericOverall
|
||||
}
|
||||
|
|
|
@ -168,16 +168,15 @@ class ConversationCreationRepositoryImpl(
|
|||
|
||||
val result: GenericOverall = if (allow) {
|
||||
ncApiCoroutines.makeRoomPublic(
|
||||
credentials,
|
||||
credentials!!,
|
||||
url
|
||||
)
|
||||
} else {
|
||||
ncApiCoroutines.makeRoomPrivate(
|
||||
credentials,
|
||||
credentials!!,
|
||||
url
|
||||
)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
|
|
@ -916,7 +916,9 @@ class ConversationInfoActivity :
|
|||
it,
|
||||
conversation!!,
|
||||
spreedCapabilities,
|
||||
conversationUser
|
||||
conversationUser,
|
||||
viewModel,
|
||||
this
|
||||
).setupGuestAccess()
|
||||
}
|
||||
if (ConversationUtils.isNoteToSelfConversation(conversation!!)) {
|
||||
|
|
|
@ -12,9 +12,11 @@ import android.util.Log
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.conversationinfo.viewmodel.ConversationInfoViewModel
|
||||
import com.nextcloud.talk.data.user.model.User
|
||||
import com.nextcloud.talk.databinding.ActivityConversationInfoBinding
|
||||
import com.nextcloud.talk.databinding.DialogPasswordBinding
|
||||
|
@ -33,9 +35,10 @@ class GuestAccessHelper(
|
|||
private val binding: ActivityConversationInfoBinding,
|
||||
private val conversation: ConversationModel,
|
||||
private val spreedCapabilities: SpreedCapability,
|
||||
private val conversationUser: User
|
||||
private val conversationUser: User,
|
||||
private val viewModel: ConversationInfoViewModel,
|
||||
private val lifecycleOwner: LifecycleOwner
|
||||
) {
|
||||
|
||||
private val conversationsRepository = activity.conversationsRepository
|
||||
private val viewThemeUtils = activity.viewThemeUtils
|
||||
private val context = activity.context
|
||||
|
@ -61,19 +64,35 @@ class GuestAccessHelper(
|
|||
binding.guestAccessView.guestAccessSettingsAllowGuest.setOnClickListener {
|
||||
val isChecked = binding.guestAccessView.allowGuestsSwitch.isChecked
|
||||
binding.guestAccessView.allowGuestsSwitch.isChecked = !isChecked
|
||||
conversationsRepository.allowGuests(
|
||||
conversation.token!!,
|
||||
!isChecked
|
||||
).subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread()).subscribe(AllowGuestsResultObserver())
|
||||
viewModel.allowGuests(conversation.token, !isChecked)
|
||||
viewModel.allowGuestsViewState.observe(lifecycleOwner) { uiState ->
|
||||
when (uiState) {
|
||||
is ConversationInfoViewModel.AllowGuestsUIState.Success -> {
|
||||
binding.guestAccessView.allowGuestsSwitch.isChecked = uiState.allow
|
||||
if (uiState.allow) {
|
||||
showAllOptions()
|
||||
} else {
|
||||
hideAllOptions()
|
||||
}
|
||||
}
|
||||
is ConversationInfoViewModel.AllowGuestsUIState.Error -> {
|
||||
val exception = uiState.exception
|
||||
val message = context.getString(R.string.nc_guest_access_allow_failed)
|
||||
Snackbar.make(binding.root, message, Snackbar.LENGTH_LONG).show()
|
||||
Log.e(TAG, message, exception)
|
||||
}
|
||||
ConversationInfoViewModel.AllowGuestsUIState.None -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.guestAccessView.guestAccessSettingsPasswordProtection.setOnClickListener {
|
||||
val isChecked = binding.guestAccessView.passwordProtectionSwitch.isChecked
|
||||
binding.guestAccessView.passwordProtectionSwitch.isChecked = !isChecked
|
||||
if (isChecked) {
|
||||
conversationsRepository.password("", conversation.token!!).subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread()).subscribe(PasswordResultObserver(false))
|
||||
viewModel.setPassword("", conversation.token)
|
||||
passwordObserver()
|
||||
} else {
|
||||
showPasswordDialog()
|
||||
}
|
||||
|
@ -85,6 +104,25 @@ class GuestAccessHelper(
|
|||
}
|
||||
}
|
||||
|
||||
private fun passwordObserver() {
|
||||
viewModel.passwordViewState.observe(lifecycleOwner) { uiState ->
|
||||
when (uiState) {
|
||||
is ConversationInfoViewModel.PasswordUiState.Success -> {
|
||||
// unused atm
|
||||
}
|
||||
is ConversationInfoViewModel.PasswordUiState.Error -> {
|
||||
val exception = uiState.exception
|
||||
val message = context.getString(R.string.nc_guest_access_password_failed)
|
||||
Snackbar.make(binding.root, message, Snackbar.LENGTH_LONG).show()
|
||||
Log.e(TAG, message, exception)
|
||||
}
|
||||
is ConversationInfoViewModel.PasswordUiState.None -> {
|
||||
// unused atm
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showPasswordDialog() {
|
||||
val builder = MaterialAlertDialogBuilder(activity)
|
||||
builder.apply {
|
||||
|
@ -94,16 +132,14 @@ class GuestAccessHelper(
|
|||
setTitle(R.string.nc_guest_access_password_dialog_title)
|
||||
setPositiveButton(R.string.nc_ok) { _, _ ->
|
||||
val password = dialogPassword.password.text.toString()
|
||||
conversationsRepository.password(password, conversation.token!!)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(PasswordResultObserver(true))
|
||||
viewModel.setPassword(password, conversation.token)
|
||||
}
|
||||
setNegativeButton(R.string.nc_cancel) { _, _ ->
|
||||
binding.guestAccessView.passwordProtectionSwitch.isChecked = false
|
||||
}
|
||||
}
|
||||
createDialog(builder)
|
||||
passwordObserver()
|
||||
}
|
||||
|
||||
private fun createDialog(builder: MaterialAlertDialogBuilder) {
|
||||
|
@ -143,32 +179,6 @@ class GuestAccessHelper(
|
|||
}
|
||||
}
|
||||
|
||||
inner class AllowGuestsResultObserver : Observer<ConversationsRepository.AllowGuestsResult> {
|
||||
|
||||
private lateinit var allowGuestsResult: ConversationsRepository.AllowGuestsResult
|
||||
|
||||
override fun onNext(t: ConversationsRepository.AllowGuestsResult) {
|
||||
allowGuestsResult = t
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
val message = context.getString(R.string.nc_guest_access_allow_failed)
|
||||
Snackbar.make(binding.root, message, Snackbar.LENGTH_LONG).show()
|
||||
Log.e(TAG, message, e)
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
binding.guestAccessView.allowGuestsSwitch.isChecked = allowGuestsResult.allow
|
||||
if (allowGuestsResult.allow) {
|
||||
showAllOptions()
|
||||
} else {
|
||||
hideAllOptions()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSubscribe(d: Disposable) = Unit
|
||||
}
|
||||
|
||||
private fun showAllOptions() {
|
||||
binding.guestAccessView.guestAccessSettingsPasswordProtection.visibility = View.VISIBLE
|
||||
if (conversationUser.capabilities?.spreedCapability?.features?.contains("sip-support") == true) {
|
||||
|
@ -181,37 +191,6 @@ class GuestAccessHelper(
|
|||
binding.guestAccessView.resendInvitationsButton.visibility = View.GONE
|
||||
}
|
||||
|
||||
inner class PasswordResultObserver(private val setPassword: Boolean) :
|
||||
Observer<ConversationsRepository.PasswordResult> {
|
||||
|
||||
private lateinit var passwordResult: ConversationsRepository.PasswordResult
|
||||
|
||||
override fun onSubscribe(d: Disposable) = Unit
|
||||
|
||||
override fun onNext(t: ConversationsRepository.PasswordResult) {
|
||||
passwordResult = t
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
val message = context.getString(R.string.nc_guest_access_password_failed)
|
||||
Snackbar.make(binding.root, message, Snackbar.LENGTH_LONG).show()
|
||||
Log.e(TAG, message, e)
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
binding.guestAccessView.passwordProtectionSwitch.isChecked = passwordResult.passwordSet && setPassword
|
||||
if (passwordResult.passwordIsWeak) {
|
||||
val builder = MaterialAlertDialogBuilder(activity)
|
||||
builder.apply {
|
||||
setTitle(R.string.nc_guest_access_password_weak_alert_title)
|
||||
setMessage(passwordResult.message)
|
||||
setPositiveButton("OK") { _, _ -> }
|
||||
}
|
||||
createDialog(builder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = GuestAccessHelper::class.simpleName
|
||||
}
|
||||
|
|
|
@ -6,12 +6,14 @@
|
|||
*/
|
||||
package com.nextcloud.talk.conversationinfo.viewmodel
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.nextcloud.talk.chat.data.network.ChatNetworkDataSource
|
||||
import com.nextcloud.talk.data.user.model.User
|
||||
import com.nextcloud.talk.models.domain.ConversationModel
|
||||
|
@ -24,6 +26,7 @@ import io.reactivex.Observer
|
|||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
class ConversationInfoViewModel @Inject constructor(
|
||||
|
@ -95,6 +98,14 @@ class ConversationInfoViewModel @Inject constructor(
|
|||
object GetCapabilitiesErrorState : ViewState
|
||||
open class GetCapabilitiesSuccessState(val spreedCapabilities: SpreedCapability) : ViewState
|
||||
|
||||
private val _allowGuestsViewState = MutableLiveData<AllowGuestsUIState>(AllowGuestsUIState.None)
|
||||
val allowGuestsViewState: LiveData<AllowGuestsUIState>
|
||||
get() = _allowGuestsViewState
|
||||
|
||||
private val _passwordViewState = MutableLiveData<PasswordUiState>(PasswordUiState.None)
|
||||
val passwordViewState: LiveData<PasswordUiState>
|
||||
get() = _passwordViewState
|
||||
|
||||
private val _getCapabilitiesViewState: MutableLiveData<ViewState> = MutableLiveData(GetCapabilitiesStartState)
|
||||
val getCapabilitiesViewState: LiveData<ViewState>
|
||||
get() = _getCapabilitiesViewState
|
||||
|
@ -233,6 +244,29 @@ class ConversationInfoViewModel @Inject constructor(
|
|||
})
|
||||
}
|
||||
|
||||
fun allowGuests(token: String, allow: Boolean) {
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
conversationsRepository.allowGuests(token, allow)
|
||||
_allowGuestsViewState.value = AllowGuestsUIState.Success(allow)
|
||||
} catch (exception: Exception) {
|
||||
_allowGuestsViewState.value = AllowGuestsUIState.Error(exception)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SuspiciousIndentation")
|
||||
fun setPassword(password: String, token: String) {
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
conversationsRepository.setPassword(password, token)
|
||||
_passwordViewState.value = PasswordUiState.Success
|
||||
} catch (exception: Exception) {
|
||||
_passwordViewState.value = PasswordUiState.Error(exception)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun archiveConversation(user: User, token: String) {
|
||||
val apiVersion = ApiUtils.getConversationApiVersion(user, intArrayOf(ApiUtils.API_V4, ApiUtils.API_V1))
|
||||
val url = ApiUtils.getUrlForArchive(apiVersion, user.baseUrl, token)
|
||||
|
@ -267,4 +301,16 @@ class ConversationInfoViewModel @Inject constructor(
|
|||
companion object {
|
||||
private val TAG = ConversationInfoViewModel::class.simpleName
|
||||
}
|
||||
|
||||
sealed class AllowGuestsUIState {
|
||||
data object None : AllowGuestsUIState()
|
||||
data class Success(val allow: Boolean) : AllowGuestsUIState()
|
||||
data class Error(val exception: Exception) : AllowGuestsUIState()
|
||||
}
|
||||
|
||||
sealed class PasswordUiState {
|
||||
data object None : PasswordUiState()
|
||||
data object Success : PasswordUiState()
|
||||
data class Error(val exception: Exception) : PasswordUiState()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,19 +12,7 @@ import io.reactivex.Observable
|
|||
|
||||
interface ConversationsRepository {
|
||||
|
||||
data class AllowGuestsResult(
|
||||
val allow: Boolean
|
||||
)
|
||||
|
||||
fun allowGuests(token: String, allow: Boolean): Observable<AllowGuestsResult>
|
||||
|
||||
data class PasswordResult(
|
||||
val passwordSet: Boolean,
|
||||
val passwordIsWeak: Boolean,
|
||||
val message: String
|
||||
)
|
||||
|
||||
fun password(password: String, token: String): Observable<PasswordResult>
|
||||
suspend fun allowGuests(token: String, allow: Boolean): GenericOverall
|
||||
|
||||
data class ResendInvitationsResult(
|
||||
val successful: Boolean
|
||||
|
@ -35,5 +23,7 @@ interface ConversationsRepository {
|
|||
|
||||
suspend fun unarchiveConversation(credentials: String, url: String): GenericOverall
|
||||
|
||||
suspend fun setPassword(password: String, token: String): GenericOverall
|
||||
|
||||
fun setConversationReadOnly(credentials: String, url: String, state: Int): Observable<GenericOverall>
|
||||
}
|
||||
|
|
|
@ -7,14 +7,10 @@
|
|||
*/
|
||||
package com.nextcloud.talk.repositories.conversations
|
||||
|
||||
import com.bluelinelabs.logansquare.LoganSquare
|
||||
import com.nextcloud.talk.api.NcApi
|
||||
import com.nextcloud.talk.api.NcApiCoroutines
|
||||
import com.nextcloud.talk.data.user.model.User
|
||||
import com.nextcloud.talk.models.json.conversations.password.PasswordOverall
|
||||
import com.nextcloud.talk.models.json.generic.GenericOverall
|
||||
import com.nextcloud.talk.repositories.conversations.ConversationsRepository.AllowGuestsResult
|
||||
import com.nextcloud.talk.repositories.conversations.ConversationsRepository.PasswordResult
|
||||
import com.nextcloud.talk.repositories.conversations.ConversationsRepository.ResendInvitationsResult
|
||||
import com.nextcloud.talk.utils.ApiUtils
|
||||
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
|
||||
|
@ -24,8 +20,7 @@ class ConversationsRepositoryImpl(
|
|||
private val api: NcApi,
|
||||
private val coroutineApi: NcApiCoroutines,
|
||||
private val userProvider: CurrentUserProviderNew
|
||||
) :
|
||||
ConversationsRepository {
|
||||
) : ConversationsRepository {
|
||||
|
||||
private val user: User
|
||||
get() = userProvider.currentUser.blockingGet()
|
||||
|
@ -33,48 +28,27 @@ class ConversationsRepositoryImpl(
|
|||
private val credentials: String
|
||||
get() = ApiUtils.getCredentials(user.username, user.token)!!
|
||||
|
||||
override fun allowGuests(token: String, allow: Boolean): Observable<AllowGuestsResult> {
|
||||
val apiVersion = ApiUtils.getConversationApiVersion(user, intArrayOf(ApiUtils.API_V4, ApiUtils.API_V1))
|
||||
|
||||
override suspend fun allowGuests(token: String, allow: Boolean): GenericOverall {
|
||||
val url = ApiUtils.getUrlForRoomPublic(
|
||||
apiVersion(),
|
||||
apiVersion,
|
||||
user.baseUrl!!,
|
||||
token
|
||||
)
|
||||
|
||||
val apiObservable = if (allow) {
|
||||
api.makeRoomPublic(
|
||||
val result: GenericOverall = if (allow) {
|
||||
coroutineApi.makeRoomPublic(
|
||||
credentials,
|
||||
url
|
||||
)
|
||||
} else {
|
||||
api.makeRoomPrivate(
|
||||
coroutineApi.makeRoomPrivate(
|
||||
credentials,
|
||||
url
|
||||
)
|
||||
}
|
||||
|
||||
return apiObservable.map { AllowGuestsResult(it.ocs!!.meta!!.statusCode == STATUS_CODE_OK && allow) }
|
||||
}
|
||||
|
||||
override fun password(password: String, token: String): Observable<PasswordResult> {
|
||||
val apiObservable = api.setPassword2(
|
||||
credentials,
|
||||
ApiUtils.getUrlForRoomPassword(
|
||||
apiVersion(),
|
||||
user.baseUrl!!,
|
||||
token
|
||||
),
|
||||
password
|
||||
)
|
||||
return apiObservable.map {
|
||||
val passwordPolicyMessage = if (it.code() == STATUS_CODE_BAD_REQUEST) {
|
||||
LoganSquare.parse(it.errorBody()!!.string(), PasswordOverall::class.java).ocs!!.data!!
|
||||
.message!!
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
||||
PasswordResult(it.isSuccessful, passwordPolicyMessage.isNotEmpty(), passwordPolicyMessage)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
override fun resendInvitations(token: String): Observable<ResendInvitationsResult> {
|
||||
|
@ -104,12 +78,24 @@ class ConversationsRepositoryImpl(
|
|||
return api.setConversationReadOnly(credentials, url, state)
|
||||
}
|
||||
|
||||
override suspend fun setPassword(password: String, token: String): GenericOverall {
|
||||
val result = coroutineApi.setPassword(
|
||||
credentials,
|
||||
ApiUtils.getUrlForRoomPassword(
|
||||
apiVersion,
|
||||
user.baseUrl!!,
|
||||
token
|
||||
),
|
||||
password
|
||||
)
|
||||
return result
|
||||
}
|
||||
|
||||
private fun apiVersion(): Int {
|
||||
return ApiUtils.getConversationApiVersion(user, intArrayOf(ApiUtils.API_V4))
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val STATUS_CODE_OK = 200
|
||||
const val STATUS_CODE_BAD_REQUEST = 400
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue