diff --git a/app/src/main/java/com/nextcloud/talk/conversationinfo/ConversationInfoActivity.kt b/app/src/main/java/com/nextcloud/talk/conversationinfo/ConversationInfoActivity.kt index 3b8837f5a..0904a79ff 100644 --- a/app/src/main/java/com/nextcloud/talk/conversationinfo/ConversationInfoActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/conversationinfo/ConversationInfoActivity.kt @@ -25,7 +25,9 @@ import androidx.appcompat.app.AlertDialog import androidx.fragment.app.FragmentTransaction import androidx.lifecycle.ViewModelProvider import androidx.work.Data +import androidx.work.ExistingWorkPolicy import androidx.work.OneTimeWorkRequest +import androidx.work.WorkInfo import androidx.work.WorkManager import autodagger.AutoInjector import com.afollestad.materialdialogs.LayoutMode.WRAP_CONTENT @@ -632,17 +634,48 @@ class ConversationInfoActivity : } private fun leaveConversation() { - workerData?.let { - WorkManager.getInstance(context).enqueue( - OneTimeWorkRequest.Builder( - LeaveConversationWorker::class - .java - ).setInputData(it).build() - ) + workerData?.let { data -> + val workRequest = OneTimeWorkRequest.Builder(LeaveConversationWorker::class.java) + .setInputData(data) + .build() - val intent = Intent(context, MainActivity::class.java) - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) - startActivity(intent) + WorkManager.getInstance(context) + .enqueueUniqueWork( + "leave_conversation_work", + ExistingWorkPolicy.REPLACE, + workRequest + ) + + WorkManager.getInstance(context).getWorkInfoByIdLiveData(workRequest.id) + .observe(this, { workInfo: WorkInfo? -> + if (workInfo != null) { + when (workInfo.state) { + WorkInfo.State.SUCCEEDED -> { + val intent = Intent(context, MainActivity::class.java) + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) + startActivity(intent) + } + WorkInfo.State.FAILED -> { + val errorType = workInfo.outputData.getString("error_type") + if (errorType == LeaveConversationWorker.ERROR_NO_OTHER_MODERATORS_OR_OWNERS_LEFT) { + Snackbar.make( + binding.root, + R.string.nc_last_moderator_leaving_room_warning, + Snackbar.LENGTH_LONG + ).show() + } else { + Snackbar.make( + binding.root, + R.string.nc_common_error_sorry, + Snackbar.LENGTH_LONG + ).show() + } + } + else -> { + } + } + } + }) } } diff --git a/app/src/main/java/com/nextcloud/talk/jobs/LeaveConversationWorker.java b/app/src/main/java/com/nextcloud/talk/jobs/LeaveConversationWorker.java deleted file mode 100644 index aee52845e..000000000 --- a/app/src/main/java/com/nextcloud/talk/jobs/LeaveConversationWorker.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Nextcloud Talk - Android Client - * - * SPDX-FileCopyrightText: 2022 Andy Scherzinger - * SPDX-FileCopyrightText: 2017-2018 Mario Danic - * SPDX-License-Identifier: GPL-3.0-or-later - */ -package com.nextcloud.talk.jobs; - -import android.content.Context; -import android.util.Log; - -import com.nextcloud.talk.api.NcApi; -import com.nextcloud.talk.application.NextcloudTalkApplication; -import com.nextcloud.talk.data.user.model.User; -import com.nextcloud.talk.events.EventStatus; -import com.nextcloud.talk.models.json.generic.GenericOverall; -import com.nextcloud.talk.users.UserManager; -import com.nextcloud.talk.utils.ApiUtils; -import com.nextcloud.talk.utils.UserIdUtils; -import com.nextcloud.talk.utils.bundle.BundleKeys; - -import org.greenrobot.eventbus.EventBus; - -import java.net.CookieManager; - -import javax.inject.Inject; - -import androidx.annotation.NonNull; -import androidx.work.Data; -import androidx.work.Worker; -import androidx.work.WorkerParameters; -import autodagger.AutoInjector; -import io.reactivex.Observer; -import io.reactivex.disposables.Disposable; -import io.reactivex.schedulers.Schedulers; -import okhttp3.JavaNetCookieJar; -import okhttp3.OkHttpClient; -import retrofit2.Retrofit; - -@AutoInjector(NextcloudTalkApplication.class) -public class LeaveConversationWorker extends Worker { - - private static final String TAG = "LeaveConversationWorker"; - - @Inject - Retrofit retrofit; - - @Inject - OkHttpClient okHttpClient; - - @Inject - UserManager userManager; - - @Inject - EventBus eventBus; - - NcApi ncApi; - - public LeaveConversationWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) { - super(context, workerParams); - NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this); - } - - @NonNull - @Override - public Result doWork() { - Data data = getInputData(); - long operationUserId = data.getLong(BundleKeys.KEY_INTERNAL_USER_ID, -1); - String conversationToken = data.getString(BundleKeys.KEY_ROOM_TOKEN); - User operationUser = userManager.getUserWithId(operationUserId).blockingGet(); - - if (operationUser != null) { - String credentials = ApiUtils.getCredentials(operationUser.getUsername(), operationUser.getToken()); - ncApi = retrofit.newBuilder().client(okHttpClient.newBuilder().cookieJar(new - JavaNetCookieJar(new CookieManager())).build()).build().create(NcApi.class); - - EventStatus eventStatus = new EventStatus(UserIdUtils.INSTANCE.getIdForUser(operationUser), - EventStatus.EventType.CONVERSATION_UPDATE, - true); - - int apiVersion = ApiUtils.getConversationApiVersion(operationUser, new int[] {ApiUtils.API_V4, 1}); - - ncApi.removeSelfFromRoom(credentials, ApiUtils.getUrlForParticipantsSelf(apiVersion, - operationUser.getBaseUrl(), - conversationToken)) - .subscribeOn(Schedulers.io()) - .blockingSubscribe(new Observer() { - Disposable disposable; - - @Override - public void onSubscribe(Disposable d) { - disposable = d; - } - - @Override - public void onNext(GenericOverall genericOverall) { - eventBus.postSticky(eventStatus); - } - - @Override - public void onError(Throwable e) { - Log.e(TAG, "failed to remove self from room", e); - } - - @Override - public void onComplete() { - disposable.dispose(); - } - }); - } - - return Result.success(); - } -} diff --git a/app/src/main/java/com/nextcloud/talk/jobs/LeaveConversationWorker.kt b/app/src/main/java/com/nextcloud/talk/jobs/LeaveConversationWorker.kt new file mode 100644 index 000000000..bf746199e --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/jobs/LeaveConversationWorker.kt @@ -0,0 +1,102 @@ +/* + * Nextcloud Talk - Android Client + * + * SPDX-FileCopyrightText: 2022 Andy Scherzinger + * SPDX-FileCopyrightText: 2017-2018 Mario Danic + * SPDX-License-Identifier: GPL-3.0-or-later + */ +package com.nextcloud.talk.jobs + +import android.annotation.SuppressLint +import android.content.Context +import android.util.Log +import androidx.work.Data +import androidx.work.ListenableWorker +import androidx.work.WorkerParameters +import androidx.work.impl.utils.futures.SettableFuture +import autodagger.AutoInjector +import com.google.common.util.concurrent.ListenableFuture +import com.nextcloud.talk.api.NcApi +import com.nextcloud.talk.application.NextcloudTalkApplication +import com.nextcloud.talk.models.json.generic.GenericOverall +import com.nextcloud.talk.users.UserManager +import com.nextcloud.talk.utils.ApiUtils +import com.nextcloud.talk.utils.ApiUtils.getConversationApiVersion +import com.nextcloud.talk.utils.ApiUtils.getCredentials +import com.nextcloud.talk.utils.ApiUtils.getUrlForParticipantsSelf +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 retrofit2.HttpException +import javax.inject.Inject + +@SuppressLint("RestrictedApi") +@AutoInjector(NextcloudTalkApplication::class) +class LeaveConversationWorker(context: Context, workerParams: WorkerParameters) : + ListenableWorker(context, workerParams) { + + @Inject + lateinit var ncApi: NcApi + + @Inject + lateinit var userManager: UserManager + + private val result = SettableFuture.create() + + override fun startWork(): ListenableFuture { + NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this) + val conversationToken = inputData.getString(BundleKeys.KEY_ROOM_TOKEN) + val currentUser = userManager.currentUser.blockingGet() + + if (currentUser != null && conversationToken != null) { + val credentials = getCredentials(currentUser.username, currentUser.token) + val apiVersion = getConversationApiVersion(currentUser, intArrayOf(ApiUtils.API_V4, 1)) + + ncApi.removeSelfFromRoom( + credentials, + getUrlForParticipantsSelf(apiVersion, currentUser.baseUrl, conversationToken) + ) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : Observer { + override fun onSubscribe(d: Disposable) { + } + + override fun onNext(p0: GenericOverall) { + } + + override fun onError(e: Throwable) { + Log.e(TAG, "Failed to remove self from room", e) + val httpException = e as? HttpException + val errorData = if (httpException?.code() == HTTP_ERROR_CODE_400) { + Data.Builder() + .putString("error_type", ERROR_NO_OTHER_MODERATORS_OR_OWNERS_LEFT) + .build() + } else { + Data.Builder() + .putString("error_type", ERROR_OTHER) + .build() + } + result.set(Result.failure(errorData)) + } + + override fun onComplete() { + result.set(Result.success()) + } + }) + } else { + result.set(Result.failure()) + } + + return result + } + + companion object { + private const val TAG = "LeaveConversationWorker" + const val ERROR_NO_OTHER_MODERATORS_OR_OWNERS_LEFT = "NO_OTHER_MODERATORS_OR_OWNERS_LEFT" + const val ERROR_OTHER = "ERROR_OTHER" + const val HTTP_ERROR_CODE_400 = 400 + } +} diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/ConversationsListBottomDialog.kt b/app/src/main/java/com/nextcloud/talk/ui/dialog/ConversationsListBottomDialog.kt index 66cff6d7b..9dbd71841 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/dialog/ConversationsListBottomDialog.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/ConversationsListBottomDialog.kt @@ -6,6 +6,7 @@ */ package com.nextcloud.talk.ui.dialog +import android.content.Intent import android.os.Bundle import android.text.TextUtils import android.view.View @@ -18,6 +19,7 @@ import autodagger.AutoInjector import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog import com.nextcloud.talk.R +import com.nextcloud.talk.activities.MainActivity import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.conversation.RenameConversationDialogFragment @@ -393,6 +395,8 @@ class ConversationsListBottomDialog( conversation.displayName ) ) + val intent = Intent(context, MainActivity::class.java) + context.startActivity(intent) } WorkInfo.State.FAILED -> { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b6d2d6469..ccd4e875f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -503,6 +503,7 @@ How to translate with transifex: Delete Message deleted successfully, but it might have been leaked to other services You are not allowed to start a call + You need to promote a new moderator before you can leave the conversation Share Send to