Merge pull request #4360 from nextcloud/last_moderator_should_delete_room

Last moderator should not leave the room
This commit is contained in:
Marcel Hibbe 2024-11-05 15:29:46 +01:00 committed by GitHub
commit f48c33d9b1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 150 additions and 125 deletions

View file

@ -27,7 +27,9 @@ import androidx.fragment.app.FragmentTransaction
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.work.Data import androidx.work.Data
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest import androidx.work.OneTimeWorkRequest
import androidx.work.WorkInfo
import androidx.work.WorkManager import androidx.work.WorkManager
import autodagger.AutoInjector import autodagger.AutoInjector
import com.afollestad.materialdialogs.LayoutMode.WRAP_CONTENT import com.afollestad.materialdialogs.LayoutMode.WRAP_CONTENT
@ -635,18 +637,49 @@ class ConversationInfoActivity :
} }
private fun leaveConversation() { private fun leaveConversation() {
workerData?.let { workerData?.let { data ->
WorkManager.getInstance(context).enqueue( val workRequest = OneTimeWorkRequest.Builder(LeaveConversationWorker::class.java)
OneTimeWorkRequest.Builder( .setInputData(data)
LeaveConversationWorker::class .build()
.java
).setInputData(it).build() 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) val intent = Intent(context, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(intent) 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 -> {
}
}
}
})
}
} }
private fun showClearHistoryDialog() { private fun showClearHistoryDialog() {

View file

@ -1,115 +0,0 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2022 Andy Scherzinger <info@andy-scherzinger.de>
* SPDX-FileCopyrightText: 2017-2018 Mario Danic <mario@lovelyhq.com>
* 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<GenericOverall>() {
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();
}
}

View file

@ -0,0 +1,102 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2022 Andy Scherzinger <info@andy-scherzinger.de>
* SPDX-FileCopyrightText: 2017-2018 Mario Danic <mario@lovelyhq.com>
* 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<Result>()
override fun startWork(): ListenableFuture<Result> {
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<GenericOverall?> {
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
}
}

View file

@ -6,6 +6,7 @@
*/ */
package com.nextcloud.talk.ui.dialog package com.nextcloud.talk.ui.dialog
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.text.TextUtils import android.text.TextUtils
import android.view.View import android.view.View
@ -18,6 +19,7 @@ import autodagger.AutoInjector
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.activities.MainActivity
import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.conversation.RenameConversationDialogFragment import com.nextcloud.talk.conversation.RenameConversationDialogFragment
@ -393,6 +395,8 @@ class ConversationsListBottomDialog(
conversation.displayName conversation.displayName
) )
) )
val intent = Intent(context, MainActivity::class.java)
context.startActivity(intent)
} }
WorkInfo.State.FAILED -> { WorkInfo.State.FAILED -> {

View file

@ -505,6 +505,7 @@ How to translate with transifex:
<string name="nc_delete_message">Delete</string> <string name="nc_delete_message">Delete</string>
<string name="nc_delete_message_leaked_to_matterbridge">Message deleted successfully, but it might have been leaked to other services</string> <string name="nc_delete_message_leaked_to_matterbridge">Message deleted successfully, but it might have been leaked to other services</string>
<string name="startCallForbidden">You are not allowed to start a call</string> <string name="startCallForbidden">You are not allowed to start a call</string>
<string name="nc_last_moderator_leaving_room_warning">You need to promote a new moderator before you can leave the conversation</string>
<string name="share">Share</string> <string name="share">Share</string>
<string name="send_to">Send to</string> <string name="send_to">Send to</string>