diff --git a/app/src/main/java/com/nextcloud/talk/contacts/ContactsActivity.kt b/app/src/main/java/com/nextcloud/talk/contacts/ContactsActivity.kt
index 6db3555bc9b..a318d20d796 100644
--- a/app/src/main/java/com/nextcloud/talk/contacts/ContactsActivity.kt
+++ b/app/src/main/java/com/nextcloud/talk/contacts/ContactsActivity.kt
@@ -41,6 +41,7 @@ import androidx.core.content.res.ResourcesCompat
 import androidx.core.view.MenuItemCompat
 import androidx.work.Data
 import androidx.work.OneTimeWorkRequest
+import androidx.work.WorkInfo
 import androidx.work.WorkManager
 import autodagger.AutoInjector
 import com.bluelinelabs.logansquare.LoganSquare
@@ -51,9 +52,10 @@ import com.nextcloud.talk.adapters.items.GenericTextHeaderItem
 import com.nextcloud.talk.api.NcApi
 import com.nextcloud.talk.application.NextcloudTalkApplication
 import com.nextcloud.talk.chat.ChatActivity
-import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum
+import com.nextcloud.talk.conversation.CreateConversationDialogFragment
 import com.nextcloud.talk.data.user.model.User
 import com.nextcloud.talk.databinding.ActivityContactsBinding
+import com.nextcloud.talk.events.EventStatus
 import com.nextcloud.talk.events.OpenConversationEvent
 import com.nextcloud.talk.jobs.AddParticipantsToConversation
 import com.nextcloud.talk.models.RetrofitBucket
@@ -64,9 +66,9 @@ import com.nextcloud.talk.models.json.conversations.RoomOverall
 import com.nextcloud.talk.models.json.converters.EnumActorTypeConverter
 import com.nextcloud.talk.models.json.participants.Participant
 import com.nextcloud.talk.openconversations.ListOpenConversationsActivity
-import com.nextcloud.talk.ui.dialog.ContactsBottomDialog
 import com.nextcloud.talk.users.UserManager
 import com.nextcloud.talk.utils.ApiUtils
+import com.nextcloud.talk.utils.UserIdUtils.getIdForUser
 import com.nextcloud.talk.utils.bundle.BundleKeys
 import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew
 import eu.davidea.flexibleadapter.FlexibleAdapter
@@ -82,7 +84,6 @@ import org.greenrobot.eventbus.Subscribe
 import org.greenrobot.eventbus.ThreadMode
 import org.parceler.Parcels
 import java.io.IOException
-import java.util.Collections
 import java.util.Locale
 import javax.inject.Inject
 
@@ -120,7 +121,6 @@ class ContactsActivity :
     private var existingParticipants: List<String>? = null
     private var isAddingParticipantsView = false
     private var conversationToken: String? = null
-    private var contactsBottomDialog: ContactsBottomDialog? = null
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
@@ -160,12 +160,8 @@ class ContactsActivity :
             toggleConversationPrivacyLayout(!isPublicCall)
         }
         if (isAddingParticipantsView) {
-            binding.joinConversationViaLink.visibility = View.GONE
             binding.callHeaderLayout.visibility = View.GONE
         } else {
-            binding.joinConversationViaLink.setOnClickListener {
-                joinConversationViaLink()
-            }
             binding.listOpenConversations.setOnClickListener {
                 listOpenConversations()
             }
@@ -228,7 +224,7 @@ class ContactsActivity :
     override fun onPrepareOptionsMenu(menu: Menu): Boolean {
         super.onPrepareOptionsMenu(menu)
         if (searchItem != null) {
-            binding?.titleTextView?.let {
+            binding.titleTextView.let {
                 viewThemeUtils.platform.colorToolbarMenuIcon(
                     it.context,
                     searchItem!!
@@ -270,7 +266,10 @@ class ContactsActivity :
     }
 
     private fun selectionDone() {
-        if (!isAddingParticipantsView) {
+        if (isAddingParticipantsView) {
+            addParticipantsToConversation()
+        } else {
+            // if there is only 1 participant, directly add him while creating room (which can only add 'one')
             if (!isPublicCall && selectedCircleIds.size + selectedGroupIds.size + selectedUserIds.size == 1) {
                 val userId: String
                 var sourceType: String? = null
@@ -290,8 +289,9 @@ class ContactsActivity :
                     }
                 }
                 createRoom(roomType, sourceType, userId)
+
+                // if there are more participants to add, ask for roomName and add them one after another
             } else {
-                val bundle = Bundle()
                 val roomType: Conversation.ConversationType = if (isPublicCall) {
                     Conversation.ConversationType.ROOM_PUBLIC_CALL
                 } else {
@@ -301,16 +301,19 @@ class ContactsActivity :
                 val groupIdsArray = ArrayList(selectedGroupIds)
                 val emailsArray = ArrayList(selectedEmails)
                 val circleIdsArray = ArrayList(selectedCircleIds)
-                bundle.putParcelable(BundleKeys.KEY_CONVERSATION_TYPE, Parcels.wrap(roomType))
-                bundle.putStringArrayList(BundleKeys.KEY_INVITED_PARTICIPANTS, userIdsArray)
-                bundle.putStringArrayList(BundleKeys.KEY_INVITED_GROUP, groupIdsArray)
-                bundle.putStringArrayList(BundleKeys.KEY_INVITED_EMAIL, emailsArray)
-                bundle.putStringArrayList(BundleKeys.KEY_INVITED_CIRCLE, circleIdsArray)
-                bundle.putSerializable(BundleKeys.KEY_OPERATION_CODE, ConversationOperationEnum.OPS_CODE_INVITE_USERS)
-                prepareAndShowBottomSheetWithBundle(bundle)
+
+                val createConversationDialog = CreateConversationDialogFragment.newInstance(
+                    userIdsArray,
+                    groupIdsArray,
+                    emailsArray,
+                    circleIdsArray,
+                    Parcels.wrap(roomType)
+                )
+                createConversationDialog.show(
+                    supportFragmentManager,
+                    TAG
+                )
             }
-        } else {
-            addParticipantsToConversation()
         }
     }
 
@@ -373,7 +376,38 @@ class ContactsActivity :
             AddParticipantsToConversation::class.java
         ).setInputData(data.build()).build()
         WorkManager.getInstance().enqueue(addParticipantsToConversationWorker)
-        finish()
+
+        WorkManager.getInstance(context).getWorkInfoByIdLiveData(addParticipantsToConversationWorker.id)
+            .observeForever { workInfo: WorkInfo? ->
+                if (workInfo != null) {
+                    when (workInfo.state) {
+                        WorkInfo.State.RUNNING -> {
+                            Log.d(TAG, "running AddParticipantsToConversation")
+                        }
+
+                        WorkInfo.State.SUCCEEDED -> {
+                            Log.d(TAG, "success AddParticipantsToConversation")
+
+                            eventBus.post(
+                                EventStatus(
+                                    getIdForUser(currentUser),
+                                    EventStatus.EventType.PARTICIPANTS_UPDATE,
+                                    true
+                                )
+                            )
+
+                            finish()
+                        }
+
+                        WorkInfo.State.FAILED -> {
+                            Log.d(TAG, "failed AddParticipantsToConversation")
+                        }
+
+                        else -> {
+                        }
+                    }
+                }
+            }
     }
 
     private fun initSearchView() {
@@ -401,14 +435,14 @@ class ContactsActivity :
     private fun fetchData() {
         dispose(null)
         alreadyFetching = true
-        userHeaderItems = HashMap<String, GenericTextHeaderItem>()
-        val query = adapter!!.getFilter(String::class.java) as String?
+        userHeaderItems = HashMap()
+        val query = adapter!!.getFilter(String::class.java)
         val retrofitBucket: RetrofitBucket =
             ApiUtils.getRetrofitBucketForContactsSearchFor14(currentUser!!.baseUrl, query)
-        val modifiedQueryMap: HashMap<String, Any?> = HashMap<String, Any?>(retrofitBucket.queryMap)
-        modifiedQueryMap.put("limit", CONTACTS_BATCH_SIZE)
+        val modifiedQueryMap: HashMap<String, Any?> = HashMap(retrofitBucket.queryMap)
+        modifiedQueryMap["limit"] = CONTACTS_BATCH_SIZE
         if (isAddingParticipantsView) {
-            modifiedQueryMap.put("itemId", conversationToken)
+            modifiedQueryMap["itemId"] = conversationToken
         }
         val shareTypesList: ArrayList<String> = ArrayList()
         // users
@@ -426,7 +460,7 @@ class ContactsActivity :
             // circles
             shareTypesList.add("7")
         }
-        modifiedQueryMap.put("shareTypes[]", shareTypesList)
+        modifiedQueryMap["shareTypes[]"] = shareTypesList
         ncApi.getContactsWithSearchParam(
             credentials,
             retrofitBucket.url,
@@ -444,7 +478,7 @@ class ContactsActivity :
                 override fun onNext(responseBody: ResponseBody) {
                     val newUserItemList = processAutocompleteUserList(responseBody)
 
-                    userHeaderItems = HashMap<String, GenericTextHeaderItem>()
+                    userHeaderItems = HashMap()
                     contactItems!!.addAll(newUserItemList)
 
                     sortUserItems(newUserItemList)
@@ -455,16 +489,16 @@ class ContactsActivity :
                         adapter?.filterItems()
                     }
 
-                    binding?.controllerGenericRv?.swipeRefreshLayout?.isRefreshing = false
+                    binding.controllerGenericRv.swipeRefreshLayout.isRefreshing = false
                 }
 
                 override fun onError(e: Throwable) {
-                    binding?.controllerGenericRv?.swipeRefreshLayout?.isRefreshing = false
+                    binding.controllerGenericRv.swipeRefreshLayout.isRefreshing = false
                     dispose(contactsQueryDisposable)
                 }
 
                 override fun onComplete() {
-                    binding?.controllerGenericRv?.swipeRefreshLayout?.isRefreshing = false
+                    binding.controllerGenericRv.swipeRefreshLayout.isRefreshing = false
                     dispose(contactsQueryDisposable)
                     alreadyFetching = false
                     disengageProgressBar()
@@ -474,18 +508,18 @@ class ContactsActivity :
 
     private fun processAutocompleteUserList(responseBody: ResponseBody): MutableList<AbstractFlexibleItem<*>> {
         try {
-            val autocompleteOverall: AutocompleteOverall = LoganSquare.parse<AutocompleteOverall>(
+            val autocompleteOverall: AutocompleteOverall = LoganSquare.parse(
                 responseBody.string(),
                 AutocompleteOverall::class.java
             )
-            val autocompleteUsersList: ArrayList<AutocompleteUser> = ArrayList<AutocompleteUser>()
+            val autocompleteUsersList: ArrayList<AutocompleteUser> = ArrayList()
             autocompleteUsersList.addAll(autocompleteOverall.ocs!!.data!!)
             return processAutocompleteUserList(autocompleteUsersList)
         } catch (ioe: IOException) {
             Log.e(TAG, "Parsing response body failed while getting contacts", ioe)
         }
 
-        return ArrayList<AbstractFlexibleItem<*>>()
+        return ArrayList()
     }
 
     private fun processAutocompleteUserList(
@@ -493,7 +527,7 @@ class ContactsActivity :
     ): MutableList<AbstractFlexibleItem<*>> {
         var participant: Participant
         val actorTypeConverter = EnumActorTypeConverter()
-        val newUserItemList: MutableList<AbstractFlexibleItem<*>> = ArrayList<AbstractFlexibleItem<*>>()
+        val newUserItemList: MutableList<AbstractFlexibleItem<*>> = ArrayList()
         for (autocompleteUser in autocompleteUsersList) {
             if (autocompleteUser.id != null &&
                 autocompleteUser.id != currentUser!!.userId &&
@@ -529,7 +563,7 @@ class ContactsActivity :
                 resources!!.getString(R.string.nc_circles)
             }
             else -> {
-                participant.displayName!!.substring(0, 1).toUpperCase(Locale.getDefault())
+                participant.displayName!!.substring(0, 1).uppercase(Locale.getDefault())
             }
         }
     }
@@ -547,76 +581,72 @@ class ContactsActivity :
         return participant
     }
 
+    @Suppress("LongMethod")
     private fun sortUserItems(newUserItemList: MutableList<AbstractFlexibleItem<*>>) {
-        Collections.sort(
-            newUserItemList,
-            { o1: AbstractFlexibleItem<*>, o2: AbstractFlexibleItem<*> ->
-                val firstName: String = if (o1 is ContactItem) {
-                    (o1 as ContactItem).model.displayName!!
-                } else {
-                    (o1 as GenericTextHeaderItem).model
-                }
-                val secondName: String = if (o2 is ContactItem) {
-                    (o2 as ContactItem).model.displayName!!
-                } else {
-                    (o2 as GenericTextHeaderItem).model
+        newUserItemList.sortWith sort@{ o1: AbstractFlexibleItem<*>, o2: AbstractFlexibleItem<*> ->
+            val firstName: String = if (o1 is ContactItem) {
+                o1.model.displayName!!
+            } else {
+                (o1 as GenericTextHeaderItem).model
+            }
+            val secondName: String = if (o2 is ContactItem) {
+                o2.model.displayName!!
+            } else {
+                (o2 as GenericTextHeaderItem).model
+            }
+            if (o1 is ContactItem && o2 is ContactItem) {
+                val firstSource: String = o1.model.source!!
+                val secondSource: String = o2.model.source!!
+                if (firstSource == secondSource) {
+                    return@sort firstName.compareTo(secondName, ignoreCase = true)
                 }
-                if (o1 is ContactItem && o2 is ContactItem) {
-                    val firstSource: String = (o1 as ContactItem).model.source!!
-                    val secondSource: String = (o2 as ContactItem).model.source!!
-                    if (firstSource == secondSource) {
-                        return@sort firstName.compareTo(secondName, ignoreCase = true)
-                    }
-
-                    // First users
-                    if ("users" == firstSource) {
-                        return@sort -1
-                    } else if ("users" == secondSource) {
-                        return@sort 1
-                    }
 
-                    // Then groups
-                    if ("groups" == firstSource) {
-                        return@sort -1
-                    } else if ("groups" == secondSource) {
-                        return@sort 1
-                    }
+                // First users
+                if ("users" == firstSource) {
+                    return@sort -1
+                } else if ("users" == secondSource) {
+                    return@sort 1
+                }
 
-                    // Then circles
-                    if ("circles" == firstSource) {
-                        return@sort -1
-                    } else if ("circles" == secondSource) {
-                        return@sort 1
-                    }
+                // Then groups
+                if ("groups" == firstSource) {
+                    return@sort -1
+                } else if ("groups" == secondSource) {
+                    return@sort 1
+                }
 
-                    // Otherwise fall back to name sorting
-                    return@sort firstName.compareTo(secondName, ignoreCase = true)
+                // Then circles
+                if ("circles" == firstSource) {
+                    return@sort -1
+                } else if ("circles" == secondSource) {
+                    return@sort 1
                 }
-                firstName.compareTo(secondName, ignoreCase = true)
+
+                // Otherwise fall back to name sorting
+                return@sort firstName.compareTo(secondName, ignoreCase = true)
             }
-        )
+            firstName.compareTo(secondName, ignoreCase = true)
+        }
 
-        Collections.sort(
-            contactItems
-        ) { o1: AbstractFlexibleItem<*>, o2: AbstractFlexibleItem<*> ->
+        contactItems?.sortWith sort@{ o1: AbstractFlexibleItem<*>, o2: AbstractFlexibleItem<*> ->
             val firstName: String = if (o1 is ContactItem) {
-                (o1 as ContactItem).model.displayName!!
+                o1.model.displayName!!
             } else {
                 (o1 as GenericTextHeaderItem).model
             }
             val secondName: String = if (o2 is ContactItem) {
-                (o2 as ContactItem).model.displayName!!
+                o2.model.displayName!!
             } else {
                 (o2 as GenericTextHeaderItem).model
             }
             if (o1 is ContactItem && o2 is ContactItem) {
-                if ("groups" == (o1 as ContactItem).model.source &&
-                    "groups" == (o2 as ContactItem).model.source
+                if ("groups" == o1.model.source &&
+                    "groups" == o2.model.source
                 ) {
                     return@sort firstName.compareTo(secondName, ignoreCase = true)
-                } else if ("groups" == (o1 as ContactItem).model.source) {
+                } else if ("groups" == o1.model.source) {
                     return@sort -1
-                } else if ("groups" == (o2 as ContactItem).model.source) {
+                } else if ("groups" == o2.model.source) {
                     return@sort 1
                 }
             }
@@ -626,24 +656,19 @@ class ContactsActivity :
 
     private fun prepareViews() {
         layoutManager = SmoothScrollLinearLayoutManager(this)
-        binding?.controllerGenericRv?.recyclerView?.layoutManager = layoutManager
-        binding?.controllerGenericRv?.recyclerView?.setHasFixedSize(true)
-        binding?.controllerGenericRv?.recyclerView?.adapter = adapter
-        binding?.controllerGenericRv?.swipeRefreshLayout?.setOnRefreshListener { fetchData() }
+        binding.controllerGenericRv.recyclerView.layoutManager = layoutManager
+        binding.controllerGenericRv.recyclerView.setHasFixedSize(true)
+        binding.controllerGenericRv.recyclerView.adapter = adapter
+        binding.controllerGenericRv.swipeRefreshLayout.setOnRefreshListener { fetchData() }
 
-        binding?.controllerGenericRv?.let { viewThemeUtils.androidx.themeSwipeRefreshLayout(it.swipeRefreshLayout) }
+        binding.controllerGenericRv.let { viewThemeUtils.androidx.themeSwipeRefreshLayout(it.swipeRefreshLayout) }
 
         binding.listOpenConversationsImage.background?.setColorFilter(
             ResourcesCompat.getColor(resources!!, R.color.colorBackgroundDarker, null),
             PorterDuff.Mode.SRC_IN
         )
 
-        binding.joinConversationViaLinkImage.background?.setColorFilter(
-            ResourcesCompat.getColor(resources!!, R.color.colorBackgroundDarker, null),
-            PorterDuff.Mode.SRC_IN
-        )
-
-        binding?.let {
+        binding.let {
             viewThemeUtils.platform.colorImageViewBackgroundAndIcon(it.publicCallLink)
         }
         disengageProgressBar()
@@ -655,7 +680,6 @@ class ContactsActivity :
             binding.controllerGenericRv.root.visibility = View.VISIBLE
             if (isNewConversationView) {
                 binding.callHeaderLayout.visibility = View.VISIBLE
-                binding.joinConversationViaLink.visibility = View.VISIBLE
             }
         }
     }
@@ -708,21 +732,12 @@ class ContactsActivity :
         }
     }
 
-    private fun prepareAndShowBottomSheetWithBundle(bundle: Bundle) {
-        // 11: create conversation-enter name for new conversation
-        // 10: get&join room when enter link
-        contactsBottomDialog = ContactsBottomDialog(this, bundle)
-        contactsBottomDialog?.show()
-    }
-
     @Subscribe(threadMode = ThreadMode.MAIN)
     fun onMessageEvent(openConversationEvent: OpenConversationEvent) {
         val chatIntent = Intent(context, ChatActivity::class.java)
         chatIntent.putExtras(openConversationEvent.bundle!!)
         chatIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
         startActivity(chatIntent)
-
-        contactsBottomDialog?.dismiss()
     }
 
     override fun onItemClick(view: View, position: Int): Boolean {
@@ -730,7 +745,6 @@ class ContactsActivity :
             if (!isNewConversationView && !isAddingParticipantsView) {
                 createRoom(adapter?.getItem(position) as ContactItem)
             } else {
-                val participant: Participant = (adapter?.getItem(position) as ContactItem).model
                 updateSelection((adapter?.getItem(position) as ContactItem))
             }
         }
@@ -840,12 +854,6 @@ class ContactsActivity :
         return "groups" == contactItem.model.source && participant.selected && adapter?.selectedItemCount!! > 1
     }
 
-    private fun joinConversationViaLink() {
-        val bundle = Bundle()
-        bundle.putSerializable(BundleKeys.KEY_OPERATION_CODE, ConversationOperationEnum.OPS_CODE_GET_AND_JOIN_ROOM)
-        prepareAndShowBottomSheetWithBundle(bundle)
-    }
-
     private fun listOpenConversations() {
         val intent = Intent(this, ListOpenConversationsActivity::class.java)
         startActivity(intent)
@@ -854,30 +862,11 @@ class ContactsActivity :
     private fun toggleCallHeader() {
         toggleConversationPrivacyLayout(isPublicCall)
         isPublicCall = !isPublicCall
-        toggleConversationViaLinkVisibility(isPublicCall)
-
         enableContactForNonPublicCall()
         checkAndHandleDoneMenuItem()
         adapter?.notifyDataSetChanged()
     }
 
-    private fun updateGroupParticipantSelection() {
-        val currentItems: List<AbstractFlexibleItem<*>> = adapter?.currentItems as
-            List<AbstractFlexibleItem<*>>
-        var internalParticipant: Participant
-        for (i in currentItems.indices) {
-            if (currentItems[i] is ContactItem) {
-                internalParticipant = (currentItems[i] as ContactItem).model
-                if (internalParticipant.calculatedActorType == Participant.ActorType.GROUPS &&
-                    internalParticipant.selected
-                ) {
-                    internalParticipant.selected = false
-                    selectedGroupIds.remove(internalParticipant.calculatedActorId)
-                }
-            }
-        }
-    }
-
     private fun enableContactForNonPublicCall() {
         for (i in 0 until adapter!!.itemCount) {
             if (adapter?.getItem(i) is ContactItem) {
@@ -891,20 +880,12 @@ class ContactsActivity :
 
     private fun toggleConversationPrivacyLayout(showInitialLayout: Boolean) {
         if (showInitialLayout) {
-            binding.initialRelativeLayout.visibility = View.VISIBLE
-            binding.secondaryRelativeLayout.visibility = View.GONE
-        } else {
-            binding.initialRelativeLayout.visibility = View.GONE
-            binding.secondaryRelativeLayout.visibility = View.VISIBLE
-        }
-    }
-
-    private fun toggleConversationViaLinkVisibility(isPublicCall: Boolean) {
-        if (isPublicCall) {
-            binding.joinConversationViaLink.visibility = View.GONE
-            updateGroupParticipantSelection()
+            binding.publicConversationCreate.visibility = View.VISIBLE
+            binding.publicConversationInfo.visibility = View.GONE
         } else {
-            binding.joinConversationViaLink.visibility = View.VISIBLE
+            binding.publicConversationCreate.visibility = View.GONE
+            binding.publicConversationInfo.visibility = View.VISIBLE
+            binding.listOpenConversations.visibility = View.GONE
         }
     }
 
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/ConversationOperationEnum.kt b/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/ConversationOperationEnum.kt
deleted file mode 100644
index 1e5979d7b55..00000000000
--- a/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/ConversationOperationEnum.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Marcel Hibbe
- * Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.nextcloud.talk.controllers.bottomsheet
-
-enum class ConversationOperationEnum {
-    OPS_CODE_RENAME_ROOM,
-    OPS_CODE_GET_AND_JOIN_ROOM,
-    OPS_CODE_INVITE_USERS,
-    OPS_CODE_MARK_AS_READ,
-    OPS_CODE_MARK_AS_UNREAD,
-    OPS_CODE_REMOVE_FAVORITE,
-    OPS_CODE_ADD_FAVORITE,
-    OPS_CODE_JOIN_ROOM
-}
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.kt b/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.kt
deleted file mode 100644
index 391e0a2f9cb..00000000000
--- a/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.kt
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Mario Danic
- * @author Marcel Hibbe
- * @author Andy Scherzinger
- * Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
- * Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
- * Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-package com.nextcloud.talk.controllers.bottomsheet
-
-import android.content.res.ColorStateList
-import android.os.Bundle
-import android.text.Editable
-import android.text.InputType
-import android.text.TextUtils
-import android.text.TextWatcher
-import android.util.Log
-import android.view.View
-import android.view.inputmethod.EditorInfo
-import androidx.core.content.res.ResourcesCompat
-import autodagger.AutoInjector
-import com.bluelinelabs.conductor.RouterTransaction
-import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
-import com.google.android.material.textfield.TextInputLayout
-import com.nextcloud.android.common.ui.theme.utils.ColorRole
-import com.nextcloud.talk.R
-import com.nextcloud.talk.api.NcApi
-import com.nextcloud.talk.application.NextcloudTalkApplication
-import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
-import com.nextcloud.talk.controllers.base.BaseController
-import com.nextcloud.talk.controllers.util.viewBinding
-import com.nextcloud.talk.data.user.model.User
-import com.nextcloud.talk.databinding.ControllerEntryMenuBinding
-import com.nextcloud.talk.models.json.conversations.Conversation
-import com.nextcloud.talk.models.json.conversations.RoomOverall
-import com.nextcloud.talk.users.UserManager
-import com.nextcloud.talk.utils.ApiUtils
-import com.nextcloud.talk.utils.UriUtils
-import com.nextcloud.talk.utils.bundle.BundleKeys
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
-import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
-import com.vanniktech.emoji.EmojiPopup
-import io.reactivex.Observer
-import io.reactivex.android.schedulers.AndroidSchedulers
-import io.reactivex.disposables.Disposable
-import io.reactivex.schedulers.Schedulers
-import okhttp3.internal.immutableListOf
-import org.greenrobot.eventbus.EventBus
-import javax.inject.Inject
-
-@AutoInjector(NextcloudTalkApplication::class)
-class EntryMenuController(args: Bundle) :
-    BaseController(
-        R.layout.controller_entry_menu,
-        args
-    ) {
-    private val binding: ControllerEntryMenuBinding? by viewBinding(ControllerEntryMenuBinding::bind)
-
-    @Inject
-    lateinit var ncApi: NcApi
-
-    @Inject
-    lateinit var eventBus: EventBus
-
-    @Inject
-    lateinit var userManager: UserManager
-
-    private val operation: ConversationOperationEnum
-    private var conversation: Conversation? = null
-    private val packageName: String
-    private val name: String
-
-    private var emojiPopup: EmojiPopup? = null
-    private val originalBundle: Bundle
-    private var currentUser: User? = null
-    private val roomToken: String
-
-    override val appBarLayoutType: AppBarLayoutType
-        get() = AppBarLayoutType.SEARCH_BAR
-
-    override fun onAttach(view: View) {
-        super.onAttach(view)
-        if (ApplicationWideMessageHolder.MessageType.CALL_PASSWORD_WRONG ==
-            ApplicationWideMessageHolder.getInstance().messageType
-        ) {
-            binding?.textInputLayout?.error = resources?.getString(R.string.nc_wrong_password)
-            ApplicationWideMessageHolder.getInstance().messageType = null
-            if (binding?.okButton?.isEnabled == true) {
-                binding?.okButton?.isEnabled = false
-                binding?.okButton?.alpha = OPACITY_BUTTON_DISABLED
-            }
-        }
-
-        emojiPopup = binding?.let {
-            EmojiPopup(
-                rootView = view,
-                editText = it.textEdit,
-                onEmojiPopupShownListener = {
-                    viewThemeUtils.platform.colorImageView(it.smileyButton, ColorRole.PRIMARY)
-                },
-                onEmojiPopupDismissListener = {
-                    it.smileyButton.imageTintList = ColorStateList.valueOf(
-                        ResourcesCompat.getColor(
-                            resources!!,
-                            R.color.medium_emphasis_text,
-                            context.theme
-                        )
-                    )
-                },
-                onEmojiClickListener = {
-                    binding?.textEdit?.editableText?.append(" ")
-                }
-            )
-        }
-    }
-
-    override fun onViewBound(view: View) {
-        super.onViewBound(view)
-
-        currentUser = userManager.currentUser.blockingGet()
-
-        if (operation == ConversationOperationEnum.OPS_CODE_GET_AND_JOIN_ROOM) {
-            binding?.textEdit?.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_URI
-
-            textEditAddChangedListener()
-
-            binding?.textInputLayout?.let { viewThemeUtils.material.colorTextInputLayout(it) }
-            binding?.okButton?.let { viewThemeUtils.material.colorMaterialButtonText(it) }
-
-            binding?.textInputLayout?.hint = resources!!.getString(R.string.nc_conversation_link)
-
-            binding?.textInputLayout?.requestFocus()
-
-            binding?.smileyButton?.setOnClickListener { onSmileyClick() }
-            binding?.okButton?.setOnClickListener { onOkButtonClick() }
-        } else if (operation == ConversationOperationEnum.OPS_CODE_INVITE_USERS) {
-            binding?.textEdit?.inputType = InputType.TYPE_CLASS_TEXT
-
-            textEditAddChangedListener()
-            binding?.smileyButton?.visibility = View.VISIBLE
-
-            binding?.textInputLayout?.let { viewThemeUtils.material.colorTextInputLayout(it) }
-            binding?.okButton?.let { viewThemeUtils.material.colorMaterialButtonText(it) }
-
-            binding?.textInputLayout?.requestFocus()
-
-            binding?.smileyButton?.setOnClickListener { onSmileyClick() }
-            binding?.okButton?.setOnClickListener { onOkButtonClick() }
-        } else {
-            val apiVersion = ApiUtils.getConversationApiVersion(currentUser, intArrayOf(ApiUtils.APIv4, ApiUtils.APIv1))
-            ncApi.getRoom(
-                ApiUtils.getCredentials(currentUser!!.username, currentUser!!.token),
-                ApiUtils.getUrlForRoom(apiVersion, currentUser!!.baseUrl, roomToken)
-            )
-                .subscribeOn(Schedulers.io())
-                .observeOn(AndroidSchedulers.mainThread())
-                .retry(1)
-                .subscribe(object : Observer<RoomOverall> {
-                    override fun onSubscribe(d: Disposable) {
-                        // unused atm
-                    }
-
-                    @Suppress("Detekt.LongMethod")
-                    override fun onNext(roomOverall: RoomOverall) {
-                        conversation = roomOverall.ocs!!.data
-
-                        if (conversation != null && operation === ConversationOperationEnum.OPS_CODE_RENAME_ROOM) {
-                            binding?.textEdit?.setText(conversation!!.name)
-                        }
-
-                        binding?.textEdit?.setOnEditorActionListener { v, actionId, event ->
-                            @Suppress("IMPLICIT_BOXING_IN_IDENTITY_EQUALS")
-                            if (actionId === EditorInfo.IME_ACTION_DONE && binding?.okButton?.isEnabled == true) {
-                                binding?.okButton?.callOnClick()
-                                return@setOnEditorActionListener true
-                            }
-                            false
-                        }
-
-                        textEditAddChangedListener()
-
-                        var labelText = ""
-                        when (operation) {
-                            ConversationOperationEnum.OPS_CODE_RENAME_ROOM -> {
-                                labelText = resources!!.getString(R.string.nc_call_name)
-                                binding?.textEdit?.inputType = InputType.TYPE_CLASS_TEXT
-                                binding?.smileyButton?.visibility = View.VISIBLE
-                            }
-
-                            ConversationOperationEnum.OPS_CODE_JOIN_ROOM -> {
-                                // 99 is joining a conversation via password
-                                labelText = resources!!.getString(R.string.nc_password)
-                                binding?.textEdit?.inputType =
-                                    InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
-                            }
-
-                            else -> {
-                            }
-                        }
-                        if (PASSWORD_ENTRY_OPERATIONS.contains(operation)) {
-                            binding?.textInputLayout?.endIconMode = TextInputLayout.END_ICON_PASSWORD_TOGGLE
-                        } else {
-                            binding?.textInputLayout?.endIconMode = TextInputLayout.END_ICON_NONE
-                        }
-
-                        binding?.textInputLayout?.let { viewThemeUtils.material.colorTextInputLayout(it) }
-                        binding?.okButton?.let { viewThemeUtils.material.colorMaterialButtonText(it) }
-
-                        binding?.textInputLayout?.hint = labelText
-                        binding?.textInputLayout?.requestFocus()
-
-                        binding?.smileyButton?.setOnClickListener { onSmileyClick() }
-                        binding?.okButton?.setOnClickListener { onOkButtonClick() }
-                    }
-
-                    override fun onError(e: Throwable) {
-                        Log.e("EntryMenuController", "error")
-                    }
-
-                    override fun onComplete() {
-                        // unused atm
-                    }
-                })
-        }
-    }
-
-    private fun textEditAddChangedListener() {
-        binding?.textEdit?.addTextChangedListener(object : TextWatcher {
-            override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
-                // unused atm
-            }
-
-            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
-                // unused atm
-            }
-
-            override fun afterTextChanged(s: Editable) {
-                if (!TextUtils.isEmpty(s)) {
-                    if (operation === ConversationOperationEnum.OPS_CODE_RENAME_ROOM) {
-                        if (conversation!!.name == null || !conversation!!.name.equals(s.toString())) {
-                            if (!binding?.okButton?.isEnabled!!) {
-                                binding?.okButton?.isEnabled = true
-                                binding?.okButton?.alpha = OPACITY_ENABLED
-                            }
-                            binding?.textInputLayout?.isErrorEnabled = false
-                        } else {
-                            if (binding?.okButton?.isEnabled == true) {
-                                binding?.okButton?.isEnabled = false
-                                binding?.okButton?.alpha = OPACITY_DISABLED
-                            }
-                            binding?.textInputLayout?.error = resources?.getString(R.string.nc_call_name_is_same)
-                        }
-                    } else if (operation !== ConversationOperationEnum.OPS_CODE_GET_AND_JOIN_ROOM) {
-                        if (!binding?.okButton?.isEnabled!!) {
-                            binding?.okButton?.isEnabled = true
-                            binding?.okButton?.alpha = OPACITY_ENABLED
-                        }
-                        binding?.textInputLayout?.isErrorEnabled = false
-                    } else if (
-                        UriUtils.hasHttpProtocolPrefixed(binding?.textEdit?.text.toString()) &&
-                        binding?.textEdit?.text.toString().contains("/call/")
-                    ) {
-                        if (!binding?.okButton?.isEnabled!!) {
-                            binding?.okButton?.isEnabled = true
-                            binding?.okButton?.alpha = OPACITY_ENABLED
-                        }
-                        binding?.textInputLayout?.isErrorEnabled = false
-                    } else {
-                        if (binding?.okButton?.isEnabled == true) {
-                            binding?.okButton?.isEnabled = false
-                            binding?.okButton?.alpha = OPACITY_DISABLED
-                        }
-                        binding?.textInputLayout?.error = resources?.getString(R.string.nc_wrong_link)
-                    }
-                } else {
-                    if (binding?.okButton?.isEnabled == true) {
-                        binding?.okButton?.isEnabled = false
-                        binding?.okButton?.alpha = OPACITY_DISABLED
-                    }
-                    binding?.textInputLayout?.isErrorEnabled = false
-                }
-            }
-        })
-    }
-
-    private fun onSmileyClick() {
-        emojiPopup?.toggle()
-    }
-
-    private fun onOkButtonClick() {
-        if (operation === ConversationOperationEnum.OPS_CODE_JOIN_ROOM) {
-            joinRoom()
-        } else if (
-            operation !== ConversationOperationEnum.OPS_CODE_GET_AND_JOIN_ROOM &&
-            operation !== ConversationOperationEnum.OPS_CODE_INVITE_USERS
-        ) {
-            val bundle = Bundle()
-            conversation!!.name = binding?.textEdit?.text.toString()
-            bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomToken)
-            bundle.putString(BundleKeys.KEY_NEW_ROOM_NAME, binding?.textEdit?.text.toString())
-            bundle.putSerializable(BundleKeys.KEY_OPERATION_CODE, operation)
-            router.pushController(
-                RouterTransaction.with(OperationsMenuController(bundle))
-                    .pushChangeHandler(HorizontalChangeHandler())
-                    .popChangeHandler(HorizontalChangeHandler())
-            )
-        } else if (operation !== ConversationOperationEnum.OPS_CODE_INVITE_USERS) {
-            val bundle = Bundle()
-            bundle.putSerializable(BundleKeys.KEY_OPERATION_CODE, operation)
-            bundle.putString(BundleKeys.KEY_CALL_URL, binding?.textEdit?.text.toString())
-            router.pushController(
-                RouterTransaction.with(OperationsMenuController(bundle))
-                    .pushChangeHandler(HorizontalChangeHandler())
-                    .popChangeHandler(HorizontalChangeHandler())
-            )
-        } else if (operation === ConversationOperationEnum.OPS_CODE_INVITE_USERS) {
-            originalBundle.putString(BundleKeys.KEY_CONVERSATION_NAME, binding?.textEdit?.text.toString())
-            router.pushController(
-                RouterTransaction.with(
-                    OperationsMenuController(
-                        originalBundle
-                    )
-                )
-                    .pushChangeHandler(HorizontalChangeHandler())
-                    .popChangeHandler(HorizontalChangeHandler())
-            )
-        }
-    }
-
-    private fun joinRoom() {
-        val bundle = Bundle()
-        bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomToken)
-        bundle.putString(BundleKeys.KEY_CONVERSATION_PASSWORD, binding?.textEdit?.text.toString())
-        bundle.putSerializable(BundleKeys.KEY_OPERATION_CODE, operation)
-        router.pushController(
-            RouterTransaction.with(OperationsMenuController(bundle))
-                .pushChangeHandler(HorizontalChangeHandler())
-                .popChangeHandler(HorizontalChangeHandler())
-        )
-    }
-
-    init {
-        sharedApplication!!.componentApplication.inject(this)
-
-        originalBundle = args
-        operation = args.getSerializable(BundleKeys.KEY_OPERATION_CODE) as ConversationOperationEnum
-        roomToken = args.getString(KEY_ROOM_TOKEN, "")
-        name = args.getString(BundleKeys.KEY_APP_ITEM_NAME, "")
-        packageName = args.getString(BundleKeys.KEY_APP_ITEM_PACKAGE_NAME, "")
-        // callUrl = args.getString(BundleKeys.KEY_CALL_URL, "")
-    }
-
-    companion object {
-        private val PASSWORD_ENTRY_OPERATIONS: List<ConversationOperationEnum> =
-            immutableListOf(
-                ConversationOperationEnum.OPS_CODE_JOIN_ROOM
-            )
-        const val OPACITY_DISABLED = 0.38f
-        const val OPACITY_BUTTON_DISABLED = 0.7f
-        const val OPACITY_ENABLED = 1.0f
-    }
-}
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.kt b/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.kt
deleted file mode 100644
index e6b083710d0..00000000000
--- a/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.kt
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Mario Danic
- * @author Andy Scherzinger
- * Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
- * Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-package com.nextcloud.talk.controllers.bottomsheet
-
-import android.os.Bundle
-import android.text.TextUtils
-import android.util.Log
-import android.view.View
-import autodagger.AutoInjector
-import com.bluelinelabs.conductor.RouterTransaction
-import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
-import com.nextcloud.android.common.ui.theme.utils.ColorRole
-import com.nextcloud.talk.R
-import com.nextcloud.talk.api.NcApi
-import com.nextcloud.talk.application.NextcloudTalkApplication
-import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
-import com.nextcloud.talk.controllers.base.BaseController
-import com.nextcloud.talk.controllers.util.viewBinding
-import com.nextcloud.talk.data.user.model.User
-import com.nextcloud.talk.databinding.ControllerOperationsMenuBinding
-import com.nextcloud.talk.events.ConversationsListFetchDataEvent
-import com.nextcloud.talk.events.OpenConversationEvent
-import com.nextcloud.talk.models.RetrofitBucket
-import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall
-import com.nextcloud.talk.models.json.conversations.Conversation
-import com.nextcloud.talk.models.json.conversations.Conversation.ConversationType
-import com.nextcloud.talk.models.json.conversations.RoomOverall
-import com.nextcloud.talk.models.json.generic.GenericOverall
-import com.nextcloud.talk.models.json.participants.AddParticipantOverall
-import com.nextcloud.talk.users.UserManager
-import com.nextcloud.talk.utils.ApiUtils
-import com.nextcloud.talk.utils.DisplayUtils
-import com.nextcloud.talk.utils.NoSupportedApiException
-import com.nextcloud.talk.utils.bundle.BundleKeys
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_CALL_URL
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_CONVERSATION_NAME
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_CONVERSATION_PASSWORD
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_CONVERSATION_TYPE
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_INVITED_GROUP
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_INVITED_PARTICIPANTS
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_NEW_ROOM_NAME
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_OPERATION_CODE
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_ID
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
-import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew
-import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
-import io.reactivex.Observer
-import io.reactivex.android.schedulers.AndroidSchedulers
-import io.reactivex.disposables.Disposable
-import io.reactivex.schedulers.Schedulers
-import org.greenrobot.eventbus.EventBus
-import org.parceler.Parcels
-import retrofit2.HttpException
-import java.io.IOException
-import java.util.Collections
-import javax.inject.Inject
-
-@AutoInjector(NextcloudTalkApplication::class)
-class OperationsMenuController(args: Bundle) : BaseController(
-    R.layout.controller_operations_menu,
-    args
-) {
-    private val binding: ControllerOperationsMenuBinding? by viewBinding(ControllerOperationsMenuBinding::bind)
-
-    @Inject
-    lateinit var ncApi: NcApi
-
-    @Inject
-    lateinit var userManager: UserManager
-
-    @Inject
-    lateinit var eventBus: EventBus
-
-    private val operation: ConversationOperationEnum?
-    private var conversation: Conversation? = null
-    private var currentUser: User? = null
-    private val callPassword: String
-    private val callUrl: String
-    private var roomToken: String
-    private val roomNameNew: String
-    private var baseUrl: String? = null
-    private var conversationToken: String? = null
-    private var disposable: Disposable? = null
-    private var conversationType: ConversationType? = null
-    private var invitedUsers: ArrayList<String>? = ArrayList()
-    private var invitedGroups: ArrayList<String>? = ArrayList()
-    private var credentials: String? = null
-    private val conversationName: String
-
-    override val appBarLayoutType: AppBarLayoutType
-        get() = AppBarLayoutType.SEARCH_BAR
-
-    override fun onViewBound(view: View) {
-        super.onViewBound(view)
-        sharedApplication!!.componentApplication.inject(this)
-        currentUser = userManager.currentUser.blockingGet()
-
-        binding?.progressBar?.let { viewThemeUtils.platform.colorCircularProgressBar(it, ColorRole.PRIMARY) }
-
-        if (!TextUtils.isEmpty(callUrl) && callUrl.contains("/call")) {
-            conversationToken = callUrl.substring(callUrl.lastIndexOf("/") + 1)
-            if (callUrl.contains("/index.php")) {
-                baseUrl = callUrl.substring(0, callUrl.indexOf("/index.php"))
-            } else {
-                baseUrl = callUrl.substring(0, callUrl.indexOf("/call"))
-            }
-        }
-
-        if (roomToken.isNotEmpty()) {
-            val apiVersion = apiVersion()
-            ncApi.getRoom(
-                credentials,
-                ApiUtils.getUrlForRoom(apiVersion, currentUser!!.baseUrl, roomToken)
-            )
-                .subscribeOn(Schedulers.io())
-                .observeOn(AndroidSchedulers.mainThread())
-                .retry(1)
-                .subscribe(object : Observer<RoomOverall> {
-                    override fun onSubscribe(d: Disposable) {
-                        disposable = d
-                    }
-
-                    override fun onNext(roomOverall: RoomOverall) {
-                        conversation = roomOverall.ocs!!.data
-
-                        if (!TextUtils.isEmpty(baseUrl) && baseUrl != currentUser!!.baseUrl) {
-                            fetchCapabilitiesForGuest()
-                        } else {
-                            processOperation()
-                        }
-                    }
-
-                    override fun onError(e: Throwable) {
-                        Log.e(TAG, "error while fetching room", e)
-                    }
-
-                    override fun onComplete() {
-                        // unused atm
-                    }
-                })
-        } else {
-            processOperation()
-        }
-    }
-
-    private fun fetchCapabilitiesForGuest() {
-        ncApi.getCapabilities(null, ApiUtils.getUrlForCapabilities(baseUrl))
-            .subscribeOn(Schedulers.io())
-            .observeOn(AndroidSchedulers.mainThread())
-            .subscribe(object : Observer<CapabilitiesOverall> {
-                override fun onSubscribe(d: Disposable) {
-                    // unused atm
-                }
-
-                override fun onNext(capabilitiesOverall: CapabilitiesOverall) {
-                    currentUser = User()
-                    currentUser!!.baseUrl = baseUrl
-                    currentUser!!.userId = "?"
-                    try {
-                        currentUser!!.capabilities = capabilitiesOverall.ocs!!.data!!.capabilities
-                    } catch (e: IOException) {
-                        Log.e("OperationsMenu", "Failed to serialize capabilities")
-                    }
-                    try {
-                        checkCapabilities(currentUser!!)
-                        processOperation()
-                    } catch (e: NoSupportedApiException) {
-                        showResultImage(everythingOK = false, isGuestSupportError = false)
-                        Log.d(TAG, "No supported server version found", e)
-                    }
-                }
-
-                override fun onError(e: Throwable) {
-                    showResultImage(everythingOK = false, isGuestSupportError = false)
-                    Log.e(TAG, "Error fetching capabilities for guest", e)
-                }
-
-                override fun onComplete() {
-                    // unused atm
-                }
-            })
-    }
-
-    @Suppress("Detekt.ComplexMethod")
-    private fun processOperation() {
-        if (currentUser == null) {
-            showResultImage(everythingOK = false, isGuestSupportError = true)
-            Log.e(TAG, "Ended up in processOperation without a valid currentUser")
-            return
-        }
-        credentials = ApiUtils.getCredentials(currentUser!!.username, currentUser!!.token)
-        when (operation) {
-            ConversationOperationEnum.OPS_CODE_RENAME_ROOM -> operationRenameRoom()
-            ConversationOperationEnum.OPS_CODE_GET_AND_JOIN_ROOM -> operationGetAndJoinRoom()
-            ConversationOperationEnum.OPS_CODE_INVITE_USERS -> operationInviteUsers()
-            ConversationOperationEnum.OPS_CODE_MARK_AS_READ -> operationMarkAsRead()
-            ConversationOperationEnum.OPS_CODE_MARK_AS_UNREAD -> operationMarkAsUnread()
-            ConversationOperationEnum.OPS_CODE_REMOVE_FAVORITE,
-            ConversationOperationEnum.OPS_CODE_ADD_FAVORITE -> operationToggleFavorite()
-
-            ConversationOperationEnum.OPS_CODE_JOIN_ROOM -> operationJoinRoom()
-            else -> {
-            }
-        }
-    }
-
-    private fun apiVersion(): Int {
-        return ApiUtils.getConversationApiVersion(currentUser, intArrayOf(ApiUtils.APIv4, ApiUtils.APIv1))
-    }
-
-    private fun chatApiVersion(): Int {
-        return ApiUtils.getChatApiVersion(currentUser, intArrayOf(ApiUtils.APIv1))
-    }
-
-    private fun operationJoinRoom() {
-        ncApi.joinRoom(
-            credentials,
-            ApiUtils.getUrlForParticipantsActive(
-                apiVersion(),
-                baseUrl,
-                conversationToken
-            ),
-            callPassword
-        )
-            .subscribeOn(Schedulers.io())
-            .observeOn(AndroidSchedulers.mainThread())
-            .retry(1)
-            .subscribe(RoomOperationsObserver())
-    }
-
-    private fun operationMarkAsRead() {
-        ncApi.setChatReadMarker(
-            credentials,
-            ApiUtils.getUrlForChatReadMarker(
-                chatApiVersion(),
-                currentUser!!.baseUrl,
-                conversation!!.token
-            ),
-            conversation!!.lastMessage!!.jsonMessageId
-        )
-            .subscribeOn(Schedulers.io())
-            .observeOn(AndroidSchedulers.mainThread())
-            .retry(1)
-            .subscribe(GenericOperationsObserver())
-    }
-
-    private fun operationMarkAsUnread() {
-        ncApi.markRoomAsUnread(
-            credentials,
-            ApiUtils.getUrlForChatReadMarker(
-                chatApiVersion(),
-                currentUser!!.baseUrl,
-                conversation!!.token
-            )
-        )
-            .subscribeOn(Schedulers.io())
-            .observeOn(AndroidSchedulers.mainThread())
-            .retry(1)
-            .subscribe(GenericOperationsObserver())
-    }
-
-    private fun operationRenameRoom() {
-        ncApi.renameRoom(
-            credentials,
-            ApiUtils.getUrlForRoom(
-                apiVersion(),
-                currentUser!!.baseUrl,
-                conversation!!.token
-            ),
-            roomNameNew
-        )
-            .subscribeOn(Schedulers.io())
-            .observeOn(AndroidSchedulers.mainThread())
-            .retry(1)
-            .subscribe(GenericOperationsObserver())
-    }
-
-    private fun operationToggleFavorite() {
-        val genericOperationsObserver = GenericOperationsObserver()
-        val apiVersion = apiVersion()
-        if (operation === ConversationOperationEnum.OPS_CODE_REMOVE_FAVORITE) {
-            ncApi.removeConversationFromFavorites(
-                credentials,
-                ApiUtils.getUrlForRoomFavorite(
-                    apiVersion,
-                    currentUser!!.baseUrl,
-                    conversation!!.token
-                )
-            )
-                .subscribeOn(Schedulers.io())
-                .observeOn(AndroidSchedulers.mainThread())
-                .retry(1)
-                .subscribe(genericOperationsObserver)
-        } else {
-            ncApi.addConversationToFavorites(
-                credentials,
-                ApiUtils.getUrlForRoomFavorite(
-                    apiVersion,
-                    currentUser!!.baseUrl,
-                    conversation!!.token
-                )
-            )
-                .subscribeOn(Schedulers.io())
-                .observeOn(AndroidSchedulers.mainThread())
-                .retry(1)
-                .subscribe(genericOperationsObserver)
-        }
-    }
-
-    private fun operationInviteUsers() {
-        val retrofitBucket: RetrofitBucket
-        val apiVersion = apiVersion()
-        var invite: String? = null
-        if (invitedGroups!!.size > 0) {
-            invite = invitedGroups!![0]
-        }
-        retrofitBucket = if (conversationType == ConversationType.ROOM_PUBLIC_CALL) {
-            ApiUtils.getRetrofitBucketForCreateRoom(
-                apiVersion,
-                currentUser!!.baseUrl,
-                "3",
-                null,
-                invite,
-                conversationName
-            )
-        } else {
-            ApiUtils.getRetrofitBucketForCreateRoom(
-                apiVersion,
-                currentUser!!.baseUrl,
-                "2",
-                null,
-                invite,
-                conversationName
-            )
-        }
-        ncApi.createRoom(credentials, retrofitBucket.url, retrofitBucket.queryMap)
-            .subscribeOn(Schedulers.io())
-            .observeOn(AndroidSchedulers.mainThread())
-            .retry(1)
-            .subscribe(object : Observer<RoomOverall> {
-                override fun onSubscribe(d: Disposable) {
-                    // unused atm
-                }
-
-                override fun onNext(roomOverall: RoomOverall) {
-                    conversation = roomOverall.ocs!!.data
-                    ncApi.getRoom(
-                        credentials,
-                        ApiUtils.getUrlForRoom(
-                            apiVersion,
-                            currentUser!!.baseUrl,
-                            conversation!!.token
-                        )
-                    )
-                        .subscribeOn(Schedulers.io())
-                        .observeOn(AndroidSchedulers.mainThread())
-                        .subscribe(object : Observer<RoomOverall> {
-                            override fun onSubscribe(d: Disposable) {
-                                // unused atm
-                            }
-
-                            override fun onNext(
-                                roomOverall: RoomOverall
-                            ) {
-                                conversation = roomOverall.ocs!!.data
-                                inviteUsersToAConversation()
-                            }
-
-                            override fun onError(e: Throwable) {
-                                showResultImage(everythingOK = false, isGuestSupportError = false)
-                                dispose()
-                            }
-
-                            override fun onComplete() {
-                                // unused atm
-                            }
-                        })
-                }
-
-                override fun onError(e: Throwable) {
-                    showResultImage(everythingOK = false, isGuestSupportError = false)
-                    dispose()
-                }
-
-                override fun onComplete() {
-                    dispose()
-                }
-            })
-    }
-
-    private fun operationGetAndJoinRoom() {
-        val apiVersion = apiVersion()
-        ncApi.getRoom(
-            credentials,
-            ApiUtils.getUrlForRoom(apiVersion, baseUrl, conversationToken)
-        )
-            .subscribeOn(Schedulers.io())
-            .observeOn(AndroidSchedulers.mainThread())
-            .retry(1)
-            .subscribe(object : Observer<RoomOverall> {
-                override fun onSubscribe(d: Disposable) {
-                    disposable = d
-                }
-
-                override fun onNext(roomOverall: RoomOverall) {
-                    conversation = roomOverall.ocs!!.data
-                    if (conversation!!.hasPassword && conversation!!.isGuest) {
-                        eventBus.post(ConversationsListFetchDataEvent())
-                        val bundle = Bundle()
-                        bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomToken)
-                        bundle.putSerializable(KEY_OPERATION_CODE, ConversationOperationEnum.OPS_CODE_JOIN_ROOM)
-                        router.pushController(
-                            RouterTransaction.with(EntryMenuController(bundle))
-                                .pushChangeHandler(HorizontalChangeHandler())
-                                .popChangeHandler(HorizontalChangeHandler())
-                        )
-                    } else if (conversation!!.isGuest) {
-                        ncApi.joinRoom(
-                            credentials,
-                            ApiUtils.getUrlForParticipantsActive(
-                                apiVersion,
-                                baseUrl,
-                                conversationToken
-                            ),
-                            null
-                        )
-                            .subscribeOn(Schedulers.io())
-                            .observeOn(AndroidSchedulers.mainThread())
-                            .subscribe(object : Observer<RoomOverall> {
-                                override fun onSubscribe(d: Disposable) {
-                                    // unused atm
-                                }
-
-                                override fun onNext(roomOverall: RoomOverall) {
-                                    conversation = roomOverall.ocs!!.data
-                                    initiateConversation()
-                                }
-
-                                override fun onError(e: Throwable) {
-                                    showResultImage(everythingOK = false, isGuestSupportError = false)
-                                    dispose()
-                                }
-
-                                override fun onComplete() {
-                                    // unused atm
-                                }
-                            })
-                    } else {
-                        initiateConversation()
-                    }
-                }
-
-                override fun onError(e: Throwable) {
-                    showResultImage(everythingOK = false, isGuestSupportError = false)
-                    dispose()
-                }
-
-                override fun onComplete() {
-                    dispose()
-                }
-            })
-    }
-
-    @Suppress("Detekt.TooGenericExceptionCaught")
-    private fun showResultImage(everythingOK: Boolean, isGuestSupportError: Boolean) {
-        try {
-            binding?.progressBar?.visibility = View.GONE
-            if (resources != null) {
-                if (everythingOK) {
-                    binding?.resultImageView?.setImageDrawable(
-                        DisplayUtils.getTintedDrawable(
-                            resources,
-                            R.drawable.ic_check_circle_black_24dp,
-                            R.color.nc_darkGreen
-                        )
-                    )
-                } else {
-                    binding?.resultImageView?.setImageDrawable(
-                        DisplayUtils.getTintedDrawable(
-                            resources,
-                            R.drawable.ic_cancel_black_24dp,
-                            R.color.nc_darkRed
-                        )
-                    )
-                }
-            }
-            binding?.resultImageView?.visibility = View.VISIBLE
-            if (everythingOK) {
-                binding?.resultTextView?.setText(R.string.nc_all_ok_operation)
-            } else {
-                binding?.resultTextView?.setTextColor(resources!!.getColor(R.color.nc_darkRed, null))
-                binding?.resultTextView?.setText(R.string.nc_failed_to_perform_operation)
-            }
-            binding?.resultTextView?.visibility = View.VISIBLE
-            if (everythingOK) {
-                eventBus.post(ConversationsListFetchDataEvent())
-            } else {
-                binding?.resultImageView?.setImageDrawable(
-                    DisplayUtils.getTintedDrawable(
-                        resources,
-                        R.drawable.ic_cancel_black_24dp,
-                        R.color.nc_darkRed
-                    )
-                )
-                binding?.okButton?.setOnClickListener { v: View? -> eventBus.post(ConversationsListFetchDataEvent()) }
-                binding?.okButton?.visibility = View.VISIBLE
-            }
-        } catch (npe: NullPointerException) {
-            Log.i(TAG, "Controller already closed", npe)
-        }
-    }
-
-    private fun dispose() {
-        if (disposable != null && !disposable!!.isDisposed) {
-            disposable!!.dispose()
-        }
-        disposable = null
-    }
-
-    public override fun onDestroy() {
-        super.onDestroy()
-        dispose()
-    }
-
-    @kotlin.Throws(NoSupportedApiException::class)
-    private fun checkCapabilities(currentUser: User) {
-        ApiUtils.getConversationApiVersion(currentUser, intArrayOf(ApiUtils.APIv4, 1))
-        ApiUtils.getCallApiVersion(currentUser, intArrayOf(ApiUtils.APIv4, 1))
-        ApiUtils.getChatApiVersion(currentUser, intArrayOf(1))
-        ApiUtils.getSignalingApiVersion(currentUser, intArrayOf(ApiUtils.APIv3, 2, 1))
-    }
-
-    private fun inviteUsersToAConversation() {
-        val localInvitedUsers = invitedUsers
-        val localInvitedGroups = invitedGroups
-        if (localInvitedGroups!!.size > 0) {
-            localInvitedGroups.removeAt(0)
-        }
-        val apiVersion = ApiUtils.getConversationApiVersion(currentUser, API_CONVERSATION_VERSIONS)
-        if (localInvitedUsers!!.size > 0 || localInvitedGroups.size > 0 &&
-            CapabilitiesUtilNew.hasSpreedFeatureCapability(currentUser, "invite-groups-and-mails")
-        ) {
-            addGroupsToConversation(localInvitedUsers, localInvitedGroups, apiVersion)
-            addUsersToConversation(localInvitedUsers, localInvitedGroups, apiVersion)
-        } else {
-            initiateConversation()
-        }
-    }
-
-    private fun addUsersToConversation(
-        localInvitedUsers: ArrayList<String>?,
-        localInvitedGroups: ArrayList<String>?,
-        apiVersion: Int
-    ) {
-        var retrofitBucket: RetrofitBucket
-        for (i in localInvitedUsers!!.indices) {
-            val userId = invitedUsers!![i]
-            retrofitBucket = ApiUtils.getRetrofitBucketForAddParticipant(
-                apiVersion,
-                currentUser!!.baseUrl,
-                conversation!!.token,
-                userId
-            )
-            ncApi.addParticipant(credentials, retrofitBucket.url, retrofitBucket.queryMap)
-                .subscribeOn(Schedulers.io())
-                .observeOn(AndroidSchedulers.mainThread())
-                .retry(1)
-                .subscribe(object : Observer<AddParticipantOverall> {
-                    override fun onSubscribe(d: Disposable) {
-                        // unused atm
-                    }
-
-                    override fun onNext(addParticipantOverall: AddParticipantOverall) {
-                        // unused atm
-                    }
-
-                    override fun onError(e: Throwable) {
-                        dispose()
-                    }
-
-                    override fun onComplete() {
-                        Collections.synchronizedList(localInvitedUsers).remove(userId)
-                        if (localInvitedGroups!!.size == 0 && localInvitedUsers.size == 0) {
-                            initiateConversation()
-                        }
-                        dispose()
-                    }
-                })
-        }
-    }
-
-    private fun addGroupsToConversation(
-        localInvitedUsers: ArrayList<String>?,
-        localInvitedGroups: ArrayList<String>?,
-        apiVersion: Int
-    ) {
-        var retrofitBucket: RetrofitBucket
-        if (localInvitedGroups!!.size > 0 &&
-            CapabilitiesUtilNew.hasSpreedFeatureCapability(currentUser, "invite-groups-and-mails")
-        ) {
-            for (i in localInvitedGroups.indices) {
-                val groupId = localInvitedGroups[i]
-                retrofitBucket = ApiUtils.getRetrofitBucketForAddParticipantWithSource(
-                    apiVersion,
-                    currentUser!!.baseUrl,
-                    conversation!!.token,
-                    "groups",
-                    groupId
-                )
-                ncApi.addParticipant(credentials, retrofitBucket.url, retrofitBucket.queryMap)
-                    .subscribeOn(Schedulers.io())
-                    .observeOn(AndroidSchedulers.mainThread())
-                    .retry(1)
-                    .subscribe(object : Observer<AddParticipantOverall> {
-                        override fun onSubscribe(d: Disposable) {
-                            // unused atm
-                        }
-
-                        override fun onNext(addParticipantOverall: AddParticipantOverall) {
-                            // unused atm
-                        }
-
-                        override fun onError(e: Throwable) {
-                            dispose()
-                        }
-
-                        override fun onComplete() {
-                            Collections.synchronizedList(localInvitedGroups).remove(groupId)
-                            if (localInvitedGroups.size == 0 && localInvitedUsers!!.size == 0) {
-                                initiateConversation()
-                            }
-                            dispose()
-                        }
-                    })
-            }
-        }
-    }
-
-    private fun initiateConversation() {
-        eventBus.post(ConversationsListFetchDataEvent())
-        val bundle = Bundle()
-        bundle.putString(KEY_ROOM_TOKEN, conversation!!.token)
-        bundle.putString(KEY_ROOM_ID, conversation!!.roomId)
-        bundle.putString(KEY_CONVERSATION_NAME, conversation!!.displayName)
-        bundle.putString(KEY_CONVERSATION_PASSWORD, callPassword)
-        eventBus.post(OpenConversationEvent(conversation, bundle))
-    }
-
-    private fun handleObserverError(e: Throwable) {
-        if (operation !== ConversationOperationEnum.OPS_CODE_JOIN_ROOM || e !is HttpException) {
-            showResultImage(everythingOK = false, isGuestSupportError = false)
-        } else {
-            val response = e.response()
-            if (response != null && response.code() == FORBIDDEN) {
-                ApplicationWideMessageHolder.getInstance()
-                    .setMessageType(ApplicationWideMessageHolder.MessageType.CALL_PASSWORD_WRONG)
-                router.popCurrentController()
-            } else {
-                showResultImage(everythingOK = false, isGuestSupportError = false)
-            }
-        }
-        dispose()
-    }
-
-    private inner class GenericOperationsObserver : Observer<GenericOverall> {
-        override fun onSubscribe(d: Disposable) {
-            disposable = d
-        }
-
-        override fun onNext(genericOverall: GenericOverall) {
-            if (operation !== ConversationOperationEnum.OPS_CODE_JOIN_ROOM) {
-                showResultImage(everythingOK = true, isGuestSupportError = false)
-            } else {
-                throw IllegalArgumentException("Unsupported operation code observed!")
-            }
-        }
-
-        override fun onError(e: Throwable) {
-            handleObserverError(e)
-        }
-
-        override fun onComplete() {
-            dispose()
-        }
-    }
-
-    private inner class RoomOperationsObserver : Observer<RoomOverall> {
-        override fun onSubscribe(d: Disposable) {
-            disposable = d
-        }
-
-        override fun onNext(roomOverall: RoomOverall) {
-            conversation = roomOverall.ocs!!.data
-            if (operation !== ConversationOperationEnum.OPS_CODE_JOIN_ROOM) {
-                showResultImage(everythingOK = true, isGuestSupportError = false)
-            } else {
-                conversation = roomOverall.ocs!!.data
-                initiateConversation()
-            }
-        }
-
-        override fun onError(e: Throwable) {
-            handleObserverError(e)
-        }
-
-        override fun onComplete() {
-            dispose()
-        }
-    }
-
-    companion object {
-        private const val TAG = "OperationsMenu"
-        private const val FORBIDDEN = 403
-        private val API_CONVERSATION_VERSIONS = intArrayOf(4, 1)
-    }
-
-    init {
-        operation = args.getSerializable(KEY_OPERATION_CODE) as ConversationOperationEnum?
-        callPassword = args.getString(KEY_CONVERSATION_PASSWORD, "")
-        callUrl = args.getString(KEY_CALL_URL, "")
-        roomToken = args.getString(KEY_ROOM_TOKEN, "")
-        roomNameNew = args.getString(KEY_NEW_ROOM_NAME, "")
-        if (args.containsKey(KEY_INVITED_PARTICIPANTS)) {
-            invitedUsers = args.getStringArrayList(KEY_INVITED_PARTICIPANTS)
-        }
-        if (args.containsKey(KEY_INVITED_GROUP)) {
-            invitedGroups = args.getStringArrayList(KEY_INVITED_GROUP)
-        }
-        if (args.containsKey(KEY_CONVERSATION_TYPE)) {
-            conversationType = Parcels.unwrap(args.getParcelable(KEY_CONVERSATION_TYPE))
-        }
-        conversationName = args.getString(KEY_CONVERSATION_NAME, "")
-    }
-}
diff --git a/app/src/main/java/com/nextcloud/talk/conversation/CreateConversationDialogFragment.kt b/app/src/main/java/com/nextcloud/talk/conversation/CreateConversationDialogFragment.kt
new file mode 100644
index 00000000000..142dc6e2745
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/conversation/CreateConversationDialogFragment.kt
@@ -0,0 +1,310 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Marcel Hibbe
+ * Copyright (C) 2023 Marcel Hibbe <dev@mhibbe.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.talk.conversation
+
+import android.annotation.SuppressLint
+import android.app.Dialog
+import android.content.Intent
+import android.content.res.ColorStateList
+import android.os.Bundle
+import android.os.Parcelable
+import android.text.Editable
+import android.text.TextUtils
+import android.text.TextWatcher
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.appcompat.app.AlertDialog
+import androidx.core.content.res.ResourcesCompat
+import androidx.fragment.app.DialogFragment
+import androidx.lifecycle.ViewModelProvider
+import androidx.work.Data
+import androidx.work.OneTimeWorkRequest
+import androidx.work.WorkInfo
+import androidx.work.WorkManager
+import autodagger.AutoInjector
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.google.android.material.snackbar.Snackbar
+import com.nextcloud.android.common.ui.theme.utils.ColorRole
+import com.nextcloud.talk.R
+import com.nextcloud.talk.application.NextcloudTalkApplication
+import com.nextcloud.talk.chat.ChatActivity
+import com.nextcloud.talk.conversation.viewmodel.ConversationViewModel
+import com.nextcloud.talk.databinding.DialogCreateConversationBinding
+import com.nextcloud.talk.jobs.AddParticipantsToConversation
+import com.nextcloud.talk.models.json.conversations.Conversation
+import com.nextcloud.talk.ui.theme.ViewThemeUtils
+import com.nextcloud.talk.utils.bundle.BundleKeys
+import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
+import com.vanniktech.emoji.EmojiPopup
+import org.greenrobot.eventbus.EventBus
+import org.parceler.Parcels
+import javax.inject.Inject
+
+@AutoInjector(NextcloudTalkApplication::class)
+class CreateConversationDialogFragment : DialogFragment() {
+
+    @Inject
+    lateinit var viewModelFactory: ViewModelProvider.Factory
+
+    @Inject
+    lateinit var viewThemeUtils: ViewThemeUtils
+
+    @Inject
+    lateinit var eventBus: EventBus
+
+    @Inject
+    lateinit var currentUserProvider: CurrentUserProviderNew
+
+    private lateinit var binding: DialogCreateConversationBinding
+    private lateinit var viewModel: ConversationViewModel
+
+    private var emojiPopup: EmojiPopup? = null
+
+    private var conversationType: Conversation.ConversationType? = null
+    private var usersToInvite: ArrayList<String> = ArrayList()
+    private var groupsToInvite: ArrayList<String> = ArrayList()
+    private var emailsToInvite: ArrayList<String> = ArrayList()
+    private var circlesToInvite: ArrayList<String> = ArrayList()
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
+
+        viewModel = ViewModelProvider(this, viewModelFactory)[ConversationViewModel::class.java]
+
+        if (arguments?.containsKey(USERS_TO_INVITE) == true) {
+            usersToInvite = arguments?.getStringArrayList(USERS_TO_INVITE)!!
+        }
+        if (arguments?.containsKey(GROUPS_TO_INVITE) == true) {
+            groupsToInvite = arguments?.getStringArrayList(GROUPS_TO_INVITE)!!
+        }
+        if (arguments?.containsKey(EMAILS_TO_INVITE) == true) {
+            emailsToInvite = arguments?.getStringArrayList(EMAILS_TO_INVITE)!!
+        }
+        if (arguments?.containsKey(CIRCLES_TO_INVITE) == true) {
+            circlesToInvite = arguments?.getStringArrayList(CIRCLES_TO_INVITE)!!
+        }
+        if (arguments?.containsKey(KEY_CONVERSATION_TYPE) == true) {
+            conversationType = Parcels.unwrap(arguments?.getParcelable(KEY_CONVERSATION_TYPE))
+        }
+    }
+
+    @SuppressLint("InflateParams")
+    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+        binding = DialogCreateConversationBinding.inflate(LayoutInflater.from(context))
+
+        val dialogBuilder = MaterialAlertDialogBuilder(binding.root.context)
+            .setTitle(resources.getString(R.string.nc_call_name))
+            // listener is null for now to avoid closing after button was clicked.
+            // listener is set later in onStart
+            .setPositiveButton(R.string.nc_common_create, null)
+            .setNegativeButton(R.string.nc_common_dismiss, null)
+            .setView(binding.root)
+        viewThemeUtils.dialog.colorMaterialAlertDialogBackground(binding.root.context, dialogBuilder)
+
+        return dialogBuilder.create()
+    }
+
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+        return binding.root
+    }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+
+        setupListeners()
+        setupStateObserver()
+
+        setupEmojiPopup()
+    }
+
+    override fun onStart() {
+        super.onStart()
+
+        val positiveButton = (dialog as AlertDialog).getButton(AlertDialog.BUTTON_POSITIVE)
+        positiveButton.isEnabled = false
+        positiveButton.setOnClickListener {
+            viewModel.createConversation(
+                binding.textEdit.text.toString(),
+                conversationType
+            )
+        }
+    }
+
+    private fun setupEmojiPopup() {
+        emojiPopup = binding.let {
+            EmojiPopup(
+                rootView = requireView(),
+                editText = it.textEdit,
+                onEmojiPopupShownListener = {
+                    viewThemeUtils.platform.colorImageView(it.smileyButton, ColorRole.PRIMARY)
+                },
+                onEmojiPopupDismissListener = {
+                    it.smileyButton.imageTintList = ColorStateList.valueOf(
+                        ResourcesCompat.getColor(
+                            resources,
+                            R.color.medium_emphasis_text,
+                            context?.theme
+                        )
+                    )
+                },
+                onEmojiClickListener = {
+                    binding.textEdit.editableText?.append(" ")
+                }
+            )
+        }
+    }
+
+    private fun setupListeners() {
+        binding.smileyButton.setOnClickListener { emojiPopup?.toggle() }
+        binding.textEdit.addTextChangedListener(object : TextWatcher {
+            override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
+                // unused atm
+            }
+
+            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
+                // unused atm
+            }
+
+            override fun afterTextChanged(s: Editable) {
+                val positiveButton = (dialog as AlertDialog).getButton(AlertDialog.BUTTON_POSITIVE)
+
+                if (!TextUtils.isEmpty(s)) {
+                    if (!positiveButton.isEnabled) {
+                        positiveButton.isEnabled = true
+                    }
+                } else {
+                    if (positiveButton.isEnabled) {
+                        positiveButton.isEnabled = false
+                    }
+                }
+            }
+        })
+    }
+
+    private fun setupStateObserver() {
+        viewModel.viewState.observe(viewLifecycleOwner) { state ->
+            when (state) {
+                is ConversationViewModel.InitialState -> {}
+                is ConversationViewModel.CreatingState -> {}
+                is ConversationViewModel.CreatingSuccessState -> addParticipants(state.roomToken)
+                is ConversationViewModel.CreatingFailedState -> {
+                    Log.e(TAG, "Failed to create conversation")
+                    showError()
+                }
+                else -> {}
+            }
+        }
+    }
+
+    private fun addParticipants(roomToken: String) {
+        val data = Data.Builder()
+        data.putLong(BundleKeys.KEY_INTERNAL_USER_ID, currentUserProvider.currentUser.blockingGet().id!!)
+        data.putString(BundleKeys.KEY_TOKEN, roomToken)
+        data.putStringArray(BundleKeys.KEY_SELECTED_USERS, usersToInvite.toTypedArray())
+        data.putStringArray(BundleKeys.KEY_SELECTED_GROUPS, groupsToInvite.toTypedArray())
+        data.putStringArray(BundleKeys.KEY_SELECTED_EMAILS, emailsToInvite.toTypedArray())
+        data.putStringArray(BundleKeys.KEY_SELECTED_CIRCLES, circlesToInvite.toTypedArray())
+
+        val addParticipantsToConversationWorker: OneTimeWorkRequest = OneTimeWorkRequest.Builder(
+            AddParticipantsToConversation::class.java
+        )
+            .setInputData(data.build())
+            .build()
+
+        WorkManager.getInstance(requireContext()).enqueue(addParticipantsToConversationWorker)
+
+        WorkManager.getInstance(requireContext()).getWorkInfoByIdLiveData(addParticipantsToConversationWorker.id)
+            .observeForever { workInfo: WorkInfo? ->
+                if (workInfo != null) {
+                    when (workInfo.state) {
+                        WorkInfo.State.RUNNING -> {
+                            Log.d(TAG, "running AddParticipantsToConversation")
+                        }
+
+                        WorkInfo.State.SUCCEEDED -> {
+                            Log.d(TAG, "success AddParticipantsToConversation")
+                            initiateConversation(roomToken)
+                        }
+
+                        WorkInfo.State.FAILED -> {
+                            Log.e(TAG, "failed to AddParticipantsToConversation")
+                            showError()
+                        }
+
+                        else -> {
+                        }
+                    }
+                }
+            }
+    }
+
+    private fun initiateConversation(roomToken: String) {
+        val bundle = Bundle()
+        bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomToken)
+
+        val chatIntent = Intent(context, ChatActivity::class.java)
+        chatIntent.putExtras(bundle)
+        chatIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+        startActivity(chatIntent)
+
+        dismiss()
+    }
+
+    private fun showError() {
+        dismiss()
+        Snackbar.make(binding.root, R.string.nc_common_error_sorry, Snackbar.LENGTH_LONG).show()
+    }
+
+    /**
+     * Fragment creator
+     */
+    companion object {
+        private val TAG = CreateConversationDialogFragment::class.java.simpleName
+        private const val USERS_TO_INVITE = "usersToInvite"
+        private const val GROUPS_TO_INVITE = "groupsToInvite"
+        private const val EMAILS_TO_INVITE = "emailsToInvite"
+        private const val CIRCLES_TO_INVITE = "circlesToInvite"
+        private const val KEY_CONVERSATION_TYPE = "keyConversationType"
+
+        @JvmStatic
+        fun newInstance(
+            usersToInvite: ArrayList<String>?,
+            groupsToInvite: ArrayList<String>?,
+            emailsToInvite: ArrayList<String>?,
+            circlesToInvite: ArrayList<String>?,
+            conversationType: Parcelable
+        ): CreateConversationDialogFragment {
+            val args = Bundle()
+            args.putStringArrayList(USERS_TO_INVITE, usersToInvite)
+            args.putStringArrayList(GROUPS_TO_INVITE, groupsToInvite)
+            args.putStringArrayList(EMAILS_TO_INVITE, emailsToInvite)
+            args.putStringArrayList(CIRCLES_TO_INVITE, circlesToInvite)
+            args.putParcelable(KEY_CONVERSATION_TYPE, conversationType)
+            val fragment = CreateConversationDialogFragment()
+            fragment.arguments = args
+            return fragment
+        }
+    }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/conversation/RenameConversationDialogFragment.kt b/app/src/main/java/com/nextcloud/talk/conversation/RenameConversationDialogFragment.kt
new file mode 100644
index 00000000000..6c0d3f08c9a
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/conversation/RenameConversationDialogFragment.kt
@@ -0,0 +1,229 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Marcel Hibbe
+ * Copyright (C) 2023 Marcel Hibbe <dev@mhibbe.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.talk.conversation
+
+import android.annotation.SuppressLint
+import android.app.Dialog
+import android.content.res.ColorStateList
+import android.os.Bundle
+import android.text.Editable
+import android.text.TextUtils
+import android.text.TextWatcher
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.appcompat.app.AlertDialog
+import androidx.core.content.res.ResourcesCompat
+import androidx.fragment.app.DialogFragment
+import androidx.lifecycle.ViewModelProvider
+import autodagger.AutoInjector
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.google.android.material.snackbar.Snackbar
+import com.nextcloud.android.common.ui.theme.utils.ColorRole
+import com.nextcloud.talk.R
+import com.nextcloud.talk.application.NextcloudTalkApplication
+import com.nextcloud.talk.conversation.viewmodel.RenameConversationViewModel
+import com.nextcloud.talk.conversationlist.ConversationsListActivity
+import com.nextcloud.talk.databinding.DialogRenameConversationBinding
+import com.nextcloud.talk.events.ConversationsListFetchDataEvent
+import com.nextcloud.talk.ui.theme.ViewThemeUtils
+import com.vanniktech.emoji.EmojiPopup
+import org.greenrobot.eventbus.EventBus
+import javax.inject.Inject
+
+@AutoInjector(NextcloudTalkApplication::class)
+class RenameConversationDialogFragment : DialogFragment() {
+
+    @Inject
+    lateinit var viewModelFactory: ViewModelProvider.Factory
+
+    @Inject
+    lateinit var viewThemeUtils: ViewThemeUtils
+
+    @Inject
+    lateinit var eventBus: EventBus
+
+    private lateinit var binding: DialogRenameConversationBinding
+    private lateinit var viewModel: RenameConversationViewModel
+
+    private var emojiPopup: EmojiPopup? = null
+
+    private var roomToken = ""
+    private var initialName = ""
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
+
+        viewModel = ViewModelProvider(this, viewModelFactory)[RenameConversationViewModel::class.java]
+        roomToken = arguments?.getString(KEY_ROOM_TOKEN)!!
+        initialName = arguments?.getString(INITIAL_NAME)!!
+    }
+
+    @SuppressLint("InflateParams")
+    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+        binding = DialogRenameConversationBinding.inflate(LayoutInflater.from(context))
+
+        val dialogBuilder = MaterialAlertDialogBuilder(binding.root.context)
+            .setTitle(resources.getString(R.string.nc_call_name))
+            // listener is null for now to avoid closing after button was clicked.
+            // listener is set later in onStart
+            .setPositiveButton(R.string.nc_rename_confirm, null)
+            .setNegativeButton(R.string.nc_common_dismiss, null)
+            .setView(binding.root)
+        viewThemeUtils.dialog.colorMaterialAlertDialogBackground(binding.root.context, dialogBuilder)
+
+        return dialogBuilder.create()
+    }
+
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+        return binding.root
+    }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+
+        setupListeners()
+        setupStateObserver()
+
+        setupEmojiPopup()
+    }
+
+    override fun onStart() {
+        super.onStart()
+        binding.textEdit.setText(initialName)
+
+        val positiveButton = (dialog as AlertDialog).getButton(AlertDialog.BUTTON_POSITIVE)
+        positiveButton.isEnabled = false
+        positiveButton.setOnClickListener {
+            viewModel.renameConversation(roomToken, binding.textEdit.text.toString())
+        }
+    }
+
+    private fun setupEmojiPopup() {
+        emojiPopup = binding.let {
+            EmojiPopup(
+                rootView = requireView(),
+                editText = it.textEdit,
+                onEmojiPopupShownListener = {
+                    viewThemeUtils.platform.colorImageView(it.smileyButton, ColorRole.PRIMARY)
+                },
+                onEmojiPopupDismissListener = {
+                    it.smileyButton.imageTintList = ColorStateList.valueOf(
+                        ResourcesCompat.getColor(
+                            resources,
+                            R.color.medium_emphasis_text,
+                            context?.theme
+                        )
+                    )
+                },
+                onEmojiClickListener = {
+                    binding.textEdit.editableText?.append(" ")
+                }
+            )
+        }
+    }
+
+    private fun setupListeners() {
+        binding.smileyButton.setOnClickListener { emojiPopup?.toggle() }
+        binding.textEdit.addTextChangedListener(object : TextWatcher {
+            override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
+                // unused atm
+            }
+
+            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
+                // unused atm
+            }
+
+            override fun afterTextChanged(s: Editable) {
+                val positiveButton = (dialog as AlertDialog).getButton(AlertDialog.BUTTON_POSITIVE)
+
+                if (!TextUtils.isEmpty(s)) {
+                    if (initialName == s.toString()) {
+                        positiveButton.isEnabled = false
+                    } else if (!positiveButton.isEnabled) {
+                        positiveButton.isEnabled = true
+                    }
+                } else {
+                    if (positiveButton.isEnabled) {
+                        positiveButton.isEnabled = false
+                    }
+                }
+            }
+        })
+    }
+
+    private fun setupStateObserver() {
+        viewModel.viewState.observe(viewLifecycleOwner) { state ->
+            when (state) {
+                is RenameConversationViewModel.InitialState -> {}
+                is RenameConversationViewModel.RenamingState -> {}
+                is RenameConversationViewModel.RenamingSuccessState -> handleSuccess()
+                is RenameConversationViewModel.RenamingFailedState -> showError()
+                else -> {}
+            }
+        }
+    }
+
+    private fun handleSuccess() {
+        eventBus.post(ConversationsListFetchDataEvent())
+
+        context?.resources?.let {
+            String.format(
+                it.getString(R.string.renamed_conversation),
+                initialName
+            )
+        }?.let {
+            (activity as ConversationsListActivity?)?.showSnackbar(
+                it
+            )
+        }
+
+        dismiss()
+    }
+
+    private fun showError() {
+        dismiss()
+        Log.e(TAG, "Failed to rename conversation")
+        Snackbar.make(binding.root, R.string.nc_common_error_sorry, Snackbar.LENGTH_LONG).show()
+    }
+
+    /**
+     * Fragment creator
+     */
+    companion object {
+        private val TAG = RenameConversationDialogFragment::class.java.simpleName
+        private const val KEY_ROOM_TOKEN = "keyRoomToken"
+        private const val INITIAL_NAME = "initialName"
+
+        @JvmStatic
+        fun newInstance(roomTokenParam: String, initialName: String): RenameConversationDialogFragment {
+            val args = Bundle()
+            args.putString(KEY_ROOM_TOKEN, roomTokenParam)
+            args.putString(INITIAL_NAME, initialName)
+            val fragment = RenameConversationDialogFragment()
+            fragment.arguments = args
+            return fragment
+        }
+    }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/conversation/repository/ConversationRepository.kt b/app/src/main/java/com/nextcloud/talk/conversation/repository/ConversationRepository.kt
new file mode 100644
index 00000000000..4e085b55675
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/conversation/repository/ConversationRepository.kt
@@ -0,0 +1,39 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Marcel Hibbe
+ * Copyright (C) 2023 Marcel Hibbe <dev@mhibbe.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.talk.conversation.repository
+
+import com.nextcloud.talk.models.json.conversations.Conversation
+import com.nextcloud.talk.models.json.conversations.RoomOverall
+import com.nextcloud.talk.models.json.generic.GenericOverall
+import io.reactivex.Observable
+
+interface ConversationRepository {
+
+    fun renameConversation(
+        roomToken: String,
+        roomNameNew: String
+    ): Observable<GenericOverall>
+
+    fun createConversation(
+        roomName: String,
+        conversationType: Conversation.ConversationType?
+    ): Observable<RoomOverall>
+}
diff --git a/app/src/main/java/com/nextcloud/talk/conversation/repository/ConversationRepositoryImpl.kt b/app/src/main/java/com/nextcloud/talk/conversation/repository/ConversationRepositoryImpl.kt
new file mode 100644
index 00000000000..6db12b27fc1
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/conversation/repository/ConversationRepositoryImpl.kt
@@ -0,0 +1,97 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Marcel Hibbe
+ * Copyright (C) 2023 Marcel Hibbe <dev@mhibbe.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.talk.conversation.repository
+
+import com.nextcloud.talk.api.NcApi
+import com.nextcloud.talk.data.user.model.User
+import com.nextcloud.talk.models.RetrofitBucket
+import com.nextcloud.talk.models.json.conversations.Conversation
+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.database.user.CurrentUserProviderNew
+import io.reactivex.Observable
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.schedulers.Schedulers
+
+class ConversationRepositoryImpl(private val ncApi: NcApi, currentUserProvider: CurrentUserProviderNew) :
+    ConversationRepository {
+
+    val currentUser: User = currentUserProvider.currentUser.blockingGet()
+    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.APIv4, ApiUtils.APIv1))
+
+        return ncApi.renameRoom(
+            credentials,
+            ApiUtils.getUrlForRoom(
+                apiVersion,
+                currentUser.baseUrl,
+                roomToken
+            ),
+            roomNameNew
+        )
+            .subscribeOn(Schedulers.io())
+            .observeOn(AndroidSchedulers.mainThread())
+            .retry(API_RETRIES)
+    }
+
+    override fun createConversation(
+        roomName: String,
+        conversationType: Conversation.ConversationType?
+    ): Observable<RoomOverall> {
+        val apiVersion = ApiUtils.getConversationApiVersion(currentUser, intArrayOf(ApiUtils.APIv4, ApiUtils.APIv1))
+
+        val retrofitBucket: RetrofitBucket = if (conversationType == Conversation.ConversationType.ROOM_PUBLIC_CALL) {
+            ApiUtils.getRetrofitBucketForCreateRoom(
+                apiVersion,
+                currentUser.baseUrl,
+                ROOM_TYPE_PUBLIC,
+                null,
+                null,
+                roomName
+            )
+        } else {
+            ApiUtils.getRetrofitBucketForCreateRoom(
+                apiVersion,
+                currentUser.baseUrl,
+                ROOM_TYPE_GROUP,
+                null,
+                null,
+                roomName
+            )
+        }
+        return ncApi.createRoom(credentials, retrofitBucket.url, retrofitBucket.queryMap)
+            .subscribeOn(Schedulers.io())
+            .observeOn(AndroidSchedulers.mainThread())
+            .retry(1)
+    }
+
+    companion object {
+        private const val ROOM_TYPE_PUBLIC = "3"
+        private const val ROOM_TYPE_GROUP = "2"
+        const val API_RETRIES: Long = 3
+    }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/conversation/viewmodel/ConversationViewModel.kt b/app/src/main/java/com/nextcloud/talk/conversation/viewmodel/ConversationViewModel.kt
new file mode 100644
index 00000000000..c35f31ced88
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/conversation/viewmodel/ConversationViewModel.kt
@@ -0,0 +1,95 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Marcel Hibbe
+ * Copyright (C) 2023 Marcel Hibbe <dev@mhibbe.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.talk.conversation.viewmodel
+
+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.conversations.Conversation
+import com.nextcloud.talk.models.json.conversations.RoomOverall
+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 ConversationViewModel @Inject constructor(private val repository: ConversationRepository) : ViewModel() {
+
+    sealed class ViewState
+    object InitialState : ViewState()
+
+    object CreatingState : ViewState()
+    class CreatingSuccessState(val roomToken: String) : ViewState()
+    object CreatingFailedState : ViewState()
+
+    private val _viewState: MutableLiveData<ViewState> = MutableLiveData(
+        InitialState
+    )
+    val viewState: LiveData<ViewState>
+        get() = _viewState
+
+    private var disposable: Disposable? = null
+
+    override fun onCleared() {
+        super.onCleared()
+        disposable?.dispose()
+    }
+
+    fun createConversation(
+        roomName: String,
+        conversationType: Conversation.ConversationType?
+    ) {
+        _viewState.value = CreatingState
+
+        repository.createConversation(
+            roomName,
+            conversationType
+        )
+            .doOnSubscribe { disposable = it }
+            ?.subscribeOn(Schedulers.io())
+            ?.observeOn(AndroidSchedulers.mainThread())
+            ?.subscribe(CreateConversationObserver())
+    }
+
+    inner class CreateConversationObserver : Observer<RoomOverall> {
+        override fun onSubscribe(d: Disposable) {
+            // unused atm
+        }
+
+        override fun onNext(roomOverall: RoomOverall) {
+            val conversation = roomOverall.ocs!!.data
+            _viewState.value = CreatingSuccessState(conversation?.token!!)
+        }
+
+        override fun onError(e: Throwable) {
+            // dispose()
+        }
+
+        override fun onComplete() {
+            // dispose()
+        }
+    }
+
+    companion object {
+        private val TAG = ConversationViewModel::class.java.simpleName
+    }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/conversation/viewmodel/RenameConversationViewModel.kt b/app/src/main/java/com/nextcloud/talk/conversation/viewmodel/RenameConversationViewModel.kt
new file mode 100644
index 00000000000..ff992d70750
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/conversation/viewmodel/RenameConversationViewModel.kt
@@ -0,0 +1,84 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Marcel Hibbe
+ * Copyright (C) 2023 Marcel Hibbe <dev@mhibbe.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+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
+    }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt b/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt
index 082af2eaa61..66666301158 100644
--- a/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt
+++ b/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt
@@ -58,6 +58,7 @@ import androidx.fragment.app.DialogFragment
 import androidx.recyclerview.widget.RecyclerView
 import androidx.work.Data
 import androidx.work.OneTimeWorkRequest
+import androidx.work.WorkInfo
 import androidx.work.WorkManager
 import autodagger.AutoInjector
 import coil.imageLoader
@@ -86,7 +87,6 @@ import com.nextcloud.talk.data.user.model.User
 import com.nextcloud.talk.databinding.ControllerConversationsRvBinding
 import com.nextcloud.talk.events.ConversationsListFetchDataEvent
 import com.nextcloud.talk.events.EventStatus
-import com.nextcloud.talk.interfaces.ConversationMenuInterface
 import com.nextcloud.talk.jobs.AccountRemovalWorker
 import com.nextcloud.talk.jobs.ContactAddressBookWorker.Companion.run
 import com.nextcloud.talk.jobs.DeleteConversationWorker
@@ -143,8 +143,7 @@ import javax.inject.Inject
 class ConversationsListActivity :
     BaseActivity(),
     FlexibleAdapter.OnItemClickListener,
-    FlexibleAdapter.OnItemLongClickListener,
-    ConversationMenuInterface {
+    FlexibleAdapter.OnItemLongClickListener {
 
     private lateinit var binding: ControllerConversationsRvBinding
 
@@ -181,7 +180,6 @@ class ConversationsListActivity :
     private var credentials: String? = null
     private var adapterWasNull = true
     private var isRefreshing = false
-    private var conversationMenuBundle: Bundle? = null
     private var showShareToScreen = false
     private var filesToShare: ArrayList<String>? = null
     private var selectedConversation: Conversation? = null
@@ -600,6 +598,9 @@ class ConversationsListActivity :
         searchItem!!.expandActionView()
     }
 
+    fun showSnackbar(text: String) {
+        Snackbar.make(binding.root, text, Snackbar.LENGTH_LONG).show()
+    }
     fun fetchRooms() {
         val includeStatus = isUserStatusAvailable(userManager.currentUser.blockingGet())
 
@@ -999,7 +1000,7 @@ class ConversationsListActivity :
 
     @SuppressLint("CheckResult") // handled by helper
     private fun loadMoreMessages() {
-        binding?.swipeRefreshLayoutView?.isRefreshing = true
+        binding.swipeRefreshLayoutView.isRefreshing = true
         val observable = searchHelper!!.loadMore()
         observable?.observeOn(AndroidSchedulers.mainThread())
             ?.subscribe({ results: MessageSearchResults -> onMessageSearchResult(results) }) { throwable: Throwable ->
@@ -1302,50 +1303,33 @@ class ConversationsListActivity :
         }, BOTTOM_SHEET_DELAY)
     }
 
-    override fun showDeleteConversationDialog(bundle: Bundle) {
-        conversationMenuBundle = bundle
-        if (conversationMenuBundle != null &&
-            isInternalUserEqualsCurrentUser(currentUser, conversationMenuBundle)
-        ) {
-            binding?.floatingActionButton?.let {
-                val dialogBuilder = MaterialAlertDialogBuilder(it.context)
-                    .setIcon(
-                        viewThemeUtils.dialog
-                            .colorMaterialAlertDialogIcon(context, R.drawable.ic_delete_black_24dp)
-                    )
-                    .setTitle(R.string.nc_delete_call)
-                    .setMessage(R.string.nc_delete_conversation_more)
-                    .setPositiveButton(R.string.nc_delete) { _, _ ->
-                        val data = Data.Builder()
-                        data.putLong(
-                            KEY_INTERNAL_USER_ID,
-                            conversationMenuBundle!!.getLong(KEY_INTERNAL_USER_ID)
-                        )
-                        data.putString(KEY_ROOM_TOKEN, bundle.getString(KEY_ROOM_TOKEN))
-                        conversationMenuBundle = null
-                        deleteConversation(data.build())
-                    }
-                    .setNegativeButton(R.string.nc_cancel) { _, _ ->
-                        conversationMenuBundle = null
-                    }
-
-                viewThemeUtils.dialog
-                    .colorMaterialAlertDialogBackground(it.context, dialogBuilder)
-                val dialog = dialogBuilder.show()
-                viewThemeUtils.platform.colorTextButtons(
-                    dialog.getButton(AlertDialog.BUTTON_POSITIVE),
-                    dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
+    fun showDeleteConversationDialog(conversation: Conversation) {
+        binding.floatingActionButton.let {
+            val dialogBuilder = MaterialAlertDialogBuilder(it.context)
+                .setIcon(
+                    viewThemeUtils.dialog
+                        .colorMaterialAlertDialogIcon(context, R.drawable.ic_delete_black_24dp)
                 )
-            }
-        }
-    }
+                .setTitle(R.string.nc_delete_call)
+                .setMessage(R.string.nc_delete_conversation_more)
+                .setPositiveButton(R.string.nc_delete) { _, _ ->
+                    deleteConversation(conversation)
+                }
+                .setNegativeButton(R.string.nc_cancel) { _, _ ->
+                }
 
-    private fun isInternalUserEqualsCurrentUser(currentUser: User?, conversationMenuBundle: Bundle?): Boolean {
-        return currentUser != null && conversationMenuBundle!!.getLong(KEY_INTERNAL_USER_ID) == currentUser.id
+            viewThemeUtils.dialog
+                .colorMaterialAlertDialogBackground(it.context, dialogBuilder)
+            val dialog = dialogBuilder.show()
+            viewThemeUtils.platform.colorTextButtons(
+                dialog.getButton(AlertDialog.BUTTON_POSITIVE),
+                dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
+            )
+        }
     }
 
     private fun showUnauthorizedDialog() {
-        binding?.floatingActionButton?.let {
+        binding.floatingActionButton.let {
             val dialogBuilder = MaterialAlertDialogBuilder(it.context)
                 .setIcon(
                     viewThemeUtils.dialog.colorMaterialAlertDialogIcon(
@@ -1517,10 +1501,40 @@ class ConversationsListActivity :
         Runtime.getRuntime().exit(0)
     }
 
-    private fun deleteConversation(data: Data) {
+    private fun deleteConversation(conversation: Conversation) {
+        val data = Data.Builder()
+        data.putLong(
+            KEY_INTERNAL_USER_ID,
+            currentUser?.id!!
+        )
+        data.putString(KEY_ROOM_TOKEN, conversation.token)
+
         val deleteConversationWorker =
-            OneTimeWorkRequest.Builder(DeleteConversationWorker::class.java).setInputData(data).build()
+            OneTimeWorkRequest.Builder(DeleteConversationWorker::class.java).setInputData(data.build()).build()
         WorkManager.getInstance().enqueue(deleteConversationWorker)
+
+        WorkManager.getInstance(context).getWorkInfoByIdLiveData(deleteConversationWorker.id)
+            .observeForever { workInfo: WorkInfo? ->
+                if (workInfo != null) {
+                    when (workInfo.state) {
+                        WorkInfo.State.SUCCEEDED -> {
+                            showSnackbar(
+                                String.format(
+                                    context.resources.getString(R.string.deleted_conversation),
+                                    conversation.displayName
+                                )
+                            )
+                        }
+
+                        WorkInfo.State.FAILED -> {
+                            showSnackbar(context.resources.getString(R.string.nc_common_error_sorry))
+                        }
+
+                        else -> {
+                        }
+                    }
+                }
+            }
     }
 
     private fun onMessageSearchResult(results: MessageSearchResults) {
diff --git a/app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt b/app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt
index 5949effb21f..9d93b2a5514 100644
--- a/app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt
+++ b/app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt
@@ -28,6 +28,8 @@ package com.nextcloud.talk.dagger.modules
 import com.nextcloud.talk.api.NcApi
 import com.nextcloud.talk.chat.data.ChatRepository
 import com.nextcloud.talk.chat.data.ChatRepositoryImpl
+import com.nextcloud.talk.conversation.repository.ConversationRepository
+import com.nextcloud.talk.conversation.repository.ConversationRepositoryImpl
 import com.nextcloud.talk.conversationinfoedit.data.ConversationInfoEditRepository
 import com.nextcloud.talk.conversationinfoedit.data.ConversationInfoEditRepositoryImpl
 import com.nextcloud.talk.data.source.local.TalkDatabase
@@ -139,4 +141,10 @@ class RepositoryModule {
         ConversationInfoEditRepository {
         return ConversationInfoEditRepositoryImpl(ncApi, userProvider)
     }
+
+    @Provides
+    fun provideConversationRepository(ncApi: NcApi, userProvider: CurrentUserProviderNew):
+        ConversationRepository {
+        return ConversationRepositoryImpl(ncApi, userProvider)
+    }
 }
diff --git a/app/src/main/java/com/nextcloud/talk/dagger/modules/ViewModelModule.kt b/app/src/main/java/com/nextcloud/talk/dagger/modules/ViewModelModule.kt
index b2a26758cff..596fb30d232 100644
--- a/app/src/main/java/com/nextcloud/talk/dagger/modules/ViewModelModule.kt
+++ b/app/src/main/java/com/nextcloud/talk/dagger/modules/ViewModelModule.kt
@@ -25,6 +25,8 @@ import androidx.lifecycle.ViewModel
 import androidx.lifecycle.ViewModelProvider
 import com.nextcloud.talk.callnotification.viewmodel.CallNotificationViewModel
 import com.nextcloud.talk.chat.viewmodels.ChatViewModel
+import com.nextcloud.talk.conversation.viewmodel.ConversationViewModel
+import com.nextcloud.talk.conversation.viewmodel.RenameConversationViewModel
 import com.nextcloud.talk.conversationinfoedit.viewmodel.ConversationInfoEditViewModel
 import com.nextcloud.talk.messagesearch.MessageSearchViewModel
 import com.nextcloud.talk.openconversations.viewmodels.OpenConversationsViewModel
@@ -132,4 +134,14 @@ abstract class ViewModelModule {
     @IntoMap
     @ViewModelKey(ConversationInfoEditViewModel::class)
     abstract fun conversationInfoEditViewModel(viewModel: ConversationInfoEditViewModel): ViewModel
+
+    @Binds
+    @IntoMap
+    @ViewModelKey(RenameConversationViewModel::class)
+    abstract fun renameConversationViewModel(viewModel: RenameConversationViewModel): ViewModel
+
+    @Binds
+    @IntoMap
+    @ViewModelKey(ConversationViewModel::class)
+    abstract fun conversationViewModel(viewModel: ConversationViewModel): ViewModel
 }
diff --git a/app/src/main/java/com/nextcloud/talk/jobs/AddParticipantsToConversation.java b/app/src/main/java/com/nextcloud/talk/jobs/AddParticipantsToConversation.java
index 4417b096c73..407ce8bca2b 100644
--- a/app/src/main/java/com/nextcloud/talk/jobs/AddParticipantsToConversation.java
+++ b/app/src/main/java/com/nextcloud/talk/jobs/AddParticipantsToConversation.java
@@ -25,11 +25,9 @@
 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.RetrofitBucket;
 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;
@@ -138,9 +136,6 @@ public Result doWork() {
             }
         }
 
-        eventBus.post(new EventStatus(UserIdUtils.INSTANCE.getIdForUser(user),
-                                      EventStatus.EventType.PARTICIPANTS_UPDATE,
-                                      true));
         return Result.success();
     }
 }
diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/ContactsBottomDialog.kt b/app/src/main/java/com/nextcloud/talk/ui/dialog/ContactsBottomDialog.kt
deleted file mode 100644
index 0e94c877cd4..00000000000
--- a/app/src/main/java/com/nextcloud/talk/ui/dialog/ContactsBottomDialog.kt
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Marcel Hibbe
- * Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.nextcloud.talk.ui.dialog
-
-import android.app.Activity
-import android.os.Bundle
-import android.view.View
-import android.view.ViewGroup
-import autodagger.AutoInjector
-import com.bluelinelabs.conductor.Conductor
-import com.bluelinelabs.conductor.Router
-import com.bluelinelabs.conductor.RouterTransaction
-import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
-import com.google.android.material.bottomsheet.BottomSheetBehavior
-import com.google.android.material.bottomsheet.BottomSheetDialog
-import com.nextcloud.talk.R
-import com.nextcloud.talk.application.NextcloudTalkApplication
-import com.nextcloud.talk.controllers.bottomsheet.EntryMenuController
-import com.nextcloud.talk.databinding.DialogBottomContactsBinding
-import com.nextcloud.talk.ui.theme.ViewThemeUtils
-import javax.inject.Inject
-
-@AutoInjector(NextcloudTalkApplication::class)
-class ContactsBottomDialog(
-    val activity: Activity,
-    val bundle: Bundle
-) : BottomSheetDialog(activity) {
-
-    @Inject
-    lateinit var viewThemeUtils: ViewThemeUtils
-
-    private var dialogRouter: Router? = null
-
-    private lateinit var binding: DialogBottomContactsBinding
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this)
-
-        binding = DialogBottomContactsBinding.inflate(layoutInflater)
-        setContentView(binding.root)
-        window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
-
-        viewThemeUtils.platform.themeDialog(binding.root)
-        executeEntryMenuController(bundle)
-    }
-
-    private fun executeEntryMenuController(bundle: Bundle) {
-        dialogRouter = Conductor.attachRouter(activity, binding.root, null)
-
-        dialogRouter!!.pushController(
-            RouterTransaction.with(EntryMenuController(bundle))
-                .pushChangeHandler(HorizontalChangeHandler())
-                .popChangeHandler(HorizontalChangeHandler())
-        )
-    }
-
-    override fun onStart() {
-        super.onStart()
-        val bottomSheet = findViewById<View>(R.id.design_bottom_sheet)
-        val behavior = BottomSheetBehavior.from(bottomSheet as View)
-        behavior.state = BottomSheetBehavior.STATE_COLLAPSED
-    }
-
-    companion object {
-        private const val TAG = "ContactsBottomDialog"
-    }
-}
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 41ccf6d9840..b64e7d61981 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
@@ -26,36 +26,31 @@ import android.view.View
 import android.view.ViewGroup
 import androidx.work.Data
 import androidx.work.OneTimeWorkRequest
+import androidx.work.WorkInfo
 import androidx.work.WorkManager
 import autodagger.AutoInjector
-import com.bluelinelabs.conductor.Conductor
-import com.bluelinelabs.conductor.Router
-import com.bluelinelabs.conductor.RouterTransaction
-import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
 import com.google.android.material.bottomsheet.BottomSheetBehavior
 import com.google.android.material.bottomsheet.BottomSheetDialog
 import com.nextcloud.talk.R
 import com.nextcloud.talk.api.NcApi
 import com.nextcloud.talk.application.NextcloudTalkApplication
-import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum
-import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_ADD_FAVORITE
-import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_MARK_AS_READ
-import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_MARK_AS_UNREAD
-import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_REMOVE_FAVORITE
-import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_RENAME_ROOM
-import com.nextcloud.talk.controllers.bottomsheet.EntryMenuController
-import com.nextcloud.talk.controllers.bottomsheet.OperationsMenuController
+import com.nextcloud.talk.conversation.RenameConversationDialogFragment
 import com.nextcloud.talk.conversationlist.ConversationsListActivity
 import com.nextcloud.talk.data.user.model.User
 import com.nextcloud.talk.databinding.DialogConversationOperationsBinding
 import com.nextcloud.talk.jobs.LeaveConversationWorker
 import com.nextcloud.talk.models.json.conversations.Conversation
+import com.nextcloud.talk.models.json.generic.GenericOverall
 import com.nextcloud.talk.ui.theme.ViewThemeUtils
 import com.nextcloud.talk.users.UserManager
+import com.nextcloud.talk.utils.ApiUtils
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_INTERNAL_USER_ID
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_OPERATION_CODE
 import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
 import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew
+import io.reactivex.Observer
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.Disposable
+import io.reactivex.schedulers.Schedulers
 import javax.inject.Inject
 
 @AutoInjector(NextcloudTalkApplication::class)
@@ -65,8 +60,6 @@ class ConversationsListBottomDialog(
     val conversation: Conversation
 ) : BottomSheetDialog(activity) {
 
-    private var dialogRouter: Router? = null
-
     private lateinit var binding: DialogConversationOperationsBinding
 
     @Inject
@@ -78,6 +71,8 @@ class ConversationsListBottomDialog(
     @Inject
     lateinit var userManager: UserManager
 
+    lateinit var credentials: String
+
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this)
@@ -90,6 +85,15 @@ class ConversationsListBottomDialog(
         initHeaderDescription()
         initItemsVisibility()
         initClickListeners()
+
+        credentials = ApiUtils.getCredentials(currentUser.username, currentUser.token)
+    }
+
+    override fun onStart() {
+        super.onStart()
+        val bottomSheet = findViewById<View>(R.id.design_bottom_sheet)
+        val behavior = BottomSheetBehavior.from(bottomSheet as View)
+        behavior.state = BottomSheetBehavior.STATE_COLLAPSED
     }
 
     private fun initHeaderDescription() {
@@ -104,18 +108,18 @@ class ConversationsListBottomDialog(
         val hasFavoritesCapability = CapabilitiesUtilNew.hasSpreedFeatureCapability(currentUser, "favorites")
         val canModerate = conversation.canModerate(currentUser)
 
-        binding.conversationOperationRemoveFavorite.visibility = setVisibleIf(
+        binding.conversationRemoveFromFavorites.visibility = setVisibleIf(
             hasFavoritesCapability && conversation.favorite
         )
-        binding.conversationOperationAddFavorite.visibility = setVisibleIf(
+        binding.conversationAddToFavorites.visibility = setVisibleIf(
             hasFavoritesCapability && !conversation.favorite
         )
 
-        binding.conversationOperationMarkAsRead.visibility = setVisibleIf(
+        binding.conversationMarkAsRead.visibility = setVisibleIf(
             conversation.unreadMessages > 0 && CapabilitiesUtilNew.canSetChatReadMarker(currentUser)
         )
 
-        binding.conversationOperationMarkAsUnread.visibility = setVisibleIf(
+        binding.conversationMarkAsUnread.visibility = setVisibleIf(
             conversation.unreadMessages <= 0 && CapabilitiesUtilNew.canMarkRoomAsUnread(currentUser)
         )
 
@@ -144,98 +148,258 @@ class ConversationsListBottomDialog(
     }
 
     private fun initClickListeners() {
-        binding.conversationOperationAddFavorite.setOnClickListener {
-            executeOperationsMenuController(OPS_CODE_ADD_FAVORITE)
+        binding.conversationAddToFavorites.setOnClickListener {
+            addConversationToFavorites()
         }
 
-        binding.conversationOperationRemoveFavorite.setOnClickListener {
-            executeOperationsMenuController(OPS_CODE_REMOVE_FAVORITE)
+        binding.conversationRemoveFromFavorites.setOnClickListener {
+            removeConversationFromFavorites()
         }
 
-        binding.conversationOperationLeave.setOnClickListener {
-            val dataBuilder = Data.Builder()
-            dataBuilder.putString(KEY_ROOM_TOKEN, conversation.token)
-            dataBuilder.putLong(KEY_INTERNAL_USER_ID, currentUser.id!!)
-            val data = dataBuilder.build()
-
-            val leaveConversationWorker =
-                OneTimeWorkRequest.Builder(LeaveConversationWorker::class.java).setInputData(
-                    data
-                ).build()
-            WorkManager.getInstance().enqueue(leaveConversationWorker)
-
-            dismiss()
+        binding.conversationMarkAsRead.setOnClickListener {
+            markConversationAsRead()
         }
 
-        binding.conversationOperationDelete.setOnClickListener {
-            if (!TextUtils.isEmpty(conversation.token)) {
-                val bundle = Bundle()
-                bundle.putLong(KEY_INTERNAL_USER_ID, currentUser.id!!)
-                bundle.putString(KEY_ROOM_TOKEN, conversation.token)
-                activity.showDeleteConversationDialog(bundle)
-            }
-
-            dismiss()
+        binding.conversationMarkAsUnread.setOnClickListener {
+            markConversationAsUnread()
         }
 
         binding.conversationOperationRename.setOnClickListener {
-            executeEntryMenuController(OPS_CODE_RENAME_ROOM)
+            renameConversation()
         }
 
-        binding.conversationOperationMarkAsRead.setOnClickListener {
-            executeOperationsMenuController(OPS_CODE_MARK_AS_READ)
+        binding.conversationOperationLeave.setOnClickListener {
+            leaveConversation()
         }
 
-        binding.conversationOperationMarkAsUnread.setOnClickListener {
-            executeOperationsMenuController(OPS_CODE_MARK_AS_UNREAD)
+        binding.conversationOperationDelete.setOnClickListener {
+            deleteConversation()
         }
     }
 
-    private fun executeOperationsMenuController(operation: ConversationOperationEnum) {
-        val bundle = Bundle()
-        bundle.putSerializable(KEY_OPERATION_CODE, operation)
-        bundle.putString(KEY_ROOM_TOKEN, conversation.token)
-
-        binding.operationItemsLayout.visibility = View.GONE
-
-        dialogRouter = Conductor.attachRouter(activity, binding.root, null)
+    private fun addConversationToFavorites() {
+        val apiVersion = ApiUtils.getConversationApiVersion(currentUser, intArrayOf(ApiUtils.APIv4, ApiUtils.APIv1))
+        ncApi.addConversationToFavorites(
+            credentials,
+            ApiUtils.getUrlForRoomFavorite(
+                apiVersion,
+                currentUser.baseUrl,
+                conversation.token
+            )
+        )
+            .subscribeOn(Schedulers.io())
+            .observeOn(AndroidSchedulers.mainThread())
+            .retry(1)
+            .subscribe(object : Observer<GenericOverall> {
+                override fun onSubscribe(d: Disposable) {
+                    // unused atm
+                }
+
+                override fun onNext(genericOverall: GenericOverall) {
+                    activity.fetchRooms()
+                    activity.showSnackbar(
+                        String.format(
+                            context.resources.getString(R.string.added_to_favorites),
+                            conversation.displayName
+                        )
+                    )
+                    dismiss()
+                }
+
+                override fun onError(e: Throwable) {
+                    activity.showSnackbar(context.resources.getString(R.string.nc_common_error_sorry))
+                    dismiss()
+                }
+
+                override fun onComplete() {
+                    // unused atm
+                }
+            })
+    }
 
-        dialogRouter!!.pushController(
-            RouterTransaction.with(OperationsMenuController(bundle))
-                .pushChangeHandler(HorizontalChangeHandler())
-                .popChangeHandler(HorizontalChangeHandler())
+    private fun removeConversationFromFavorites() {
+        val apiVersion = ApiUtils.getConversationApiVersion(currentUser, intArrayOf(ApiUtils.APIv4, ApiUtils.APIv1))
+        ncApi.removeConversationFromFavorites(
+            credentials,
+            ApiUtils.getUrlForRoomFavorite(
+                apiVersion,
+                currentUser.baseUrl,
+                conversation.token
+            )
         )
+            .subscribeOn(Schedulers.io())
+            .observeOn(AndroidSchedulers.mainThread())
+            .retry(1)
+            .subscribe(object : Observer<GenericOverall> {
+                override fun onSubscribe(d: Disposable) {
+                    // unused atm
+                }
+
+                override fun onNext(genericOverall: GenericOverall) {
+                    activity.fetchRooms()
+                    activity.showSnackbar(
+                        String.format(
+                            context.resources.getString(R.string.removed_from_favorites),
+                            conversation.displayName
+                        )
+                    )
+                    dismiss()
+                }
+
+                override fun onError(e: Throwable) {
+                    activity.showSnackbar(context.resources.getString(R.string.nc_common_error_sorry))
+                    dismiss()
+                }
+
+                override fun onComplete() {
+                    // unused atm
+                }
+            })
+    }
 
-        activity.fetchRooms()
+    private fun markConversationAsUnread() {
+        ncApi.markRoomAsUnread(
+            credentials,
+            ApiUtils.getUrlForChatReadMarker(
+                chatApiVersion(),
+                currentUser.baseUrl,
+                conversation.token
+            )
+        )
+            .subscribeOn(Schedulers.io())
+            .observeOn(AndroidSchedulers.mainThread())
+            .retry(1)
+            .subscribe(object : Observer<GenericOverall> {
+                override fun onSubscribe(d: Disposable) {
+                    // unused atm
+                }
+
+                override fun onNext(genericOverall: GenericOverall) {
+                    activity.fetchRooms()
+                    activity.showSnackbar(
+                        String.format(
+                            context.resources.getString(R.string.marked_as_unread),
+                            conversation.displayName
+                        )
+                    )
+                    dismiss()
+                }
+
+                override fun onError(e: Throwable) {
+                    activity.showSnackbar(context.resources.getString(R.string.nc_common_error_sorry))
+                    dismiss()
+                }
+
+                override fun onComplete() {
+                    // unused atm
+                }
+            })
     }
 
-    private fun executeEntryMenuController(operation: ConversationOperationEnum) {
-        val bundle = Bundle()
-        bundle.putSerializable(KEY_OPERATION_CODE, operation)
-        bundle.putString(KEY_ROOM_TOKEN, conversation.token)
+    private fun markConversationAsRead() {
+        ncApi.setChatReadMarker(
+            credentials,
+            ApiUtils.getUrlForChatReadMarker(
+                chatApiVersion(),
+                currentUser.baseUrl,
+                conversation.token
+            ),
+            conversation.lastMessage!!.jsonMessageId
+        )
+            .subscribeOn(Schedulers.io())
+            .observeOn(AndroidSchedulers.mainThread())
+            .retry(1)
+            .subscribe(object : Observer<GenericOverall> {
+                override fun onSubscribe(d: Disposable) {
+                    // unused atm
+                }
+
+                override fun onNext(genericOverall: GenericOverall) {
+                    activity.fetchRooms()
+                    activity.showSnackbar(
+                        String.format(
+                            context.resources.getString(R.string.marked_as_read),
+                            conversation.displayName
+                        )
+                    )
+                    dismiss()
+                }
+
+                override fun onError(e: Throwable) {
+                    activity.showSnackbar(context.resources.getString(R.string.nc_common_error_sorry))
+                    dismiss()
+                }
+
+                override fun onComplete() {
+                    // unused atm
+                }
+            })
+    }
 
-        binding.operationItemsLayout.visibility = View.GONE
+    private fun renameConversation() {
+        if (!TextUtils.isEmpty(conversation.token)) {
+            dismiss()
+            val conversationDialog = RenameConversationDialogFragment.newInstance(
+                conversation.token!!,
+                conversation.displayName!!
+            )
+            conversationDialog.show(
+                activity.supportFragmentManager,
+                TAG
+            )
+        }
+    }
+    private fun leaveConversation() {
+        val dataBuilder = Data.Builder()
+        dataBuilder.putString(KEY_ROOM_TOKEN, conversation.token)
+        dataBuilder.putLong(KEY_INTERNAL_USER_ID, currentUser.id!!)
+        val data = dataBuilder.build()
+
+        val leaveConversationWorker =
+            OneTimeWorkRequest.Builder(LeaveConversationWorker::class.java).setInputData(
+                data
+            ).build()
+        WorkManager.getInstance().enqueue(leaveConversationWorker)
+
+        WorkManager.getInstance(context).getWorkInfoByIdLiveData(leaveConversationWorker.id)
+            .observeForever { workInfo: WorkInfo? ->
+                if (workInfo != null) {
+                    when (workInfo.state) {
+                        WorkInfo.State.SUCCEEDED -> {
+                            activity.showSnackbar(
+                                String.format(
+                                    context.resources.getString(R.string.left_conversation),
+                                    conversation.displayName
+                                )
+                            )
+                        }
+
+                        WorkInfo.State.FAILED -> {
+                            activity.showSnackbar(context.resources.getString(R.string.nc_common_error_sorry))
+                        }
+
+                        else -> {
+                        }
+                    }
+                }
+            }
 
-        dialogRouter = Conductor.attachRouter(activity, binding.root, null)
+        dismiss()
+    }
 
-        dialogRouter!!.pushController(
+    private fun deleteConversation() {
+        if (!TextUtils.isEmpty(conversation.token)) {
+            activity.showDeleteConversationDialog(conversation)
+        }
 
-            // TODO refresh conversation list after EntryMenuController finished (throw event? / pass controller
-            //  into EntryMenuController to execute fetch data... ?!)
-            // for example if you set a password, the dialog items should be refreshed for the next time you open it
-            // without to manually have to refresh the conversations list
-            // also see BottomSheetLockEvent ??
+        dismiss()
+    }
 
-            RouterTransaction.with(EntryMenuController(bundle))
-                .pushChangeHandler(HorizontalChangeHandler())
-                .popChangeHandler(HorizontalChangeHandler())
-        )
+    private fun chatApiVersion(): Int {
+        return ApiUtils.getChatApiVersion(currentUser, intArrayOf(ApiUtils.APIv1))
     }
 
-    override fun onStart() {
-        super.onStart()
-        val bottomSheet = findViewById<View>(R.id.design_bottom_sheet)
-        val behavior = BottomSheetBehavior.from(bottomSheet as View)
-        behavior.state = BottomSheetBehavior.STATE_COLLAPSED
+    companion object {
+        val TAG = ConversationsListBottomDialog::class.simpleName
     }
 }
diff --git a/app/src/main/java/com/nextcloud/talk/utils/remapchat/RemapChatModel.kt b/app/src/main/java/com/nextcloud/talk/utils/remapchat/RemapChatModel.kt
deleted file mode 100644
index 6f4e42e4660..00000000000
--- a/app/src/main/java/com/nextcloud/talk/utils/remapchat/RemapChatModel.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.nextcloud.talk.utils.remapchat
-
-import android.os.Bundle
-import com.bluelinelabs.conductor.ControllerChangeHandler
-import com.bluelinelabs.conductor.Router
-
-data class RemapChatModel(
-    val router: Router,
-    val controllerChangeHandler: ControllerChangeHandler,
-    val chatControllerTag: String,
-    val bundle: Bundle
-)
diff --git a/app/src/main/res/drawable/ic_check_circle_black_24dp.xml b/app/src/main/res/drawable/ic_check_circle_black_24dp.xml
deleted file mode 100644
index 00195584ded..00000000000
--- a/app/src/main/res/drawable/ic_check_circle_black_24dp.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-  ~ Nextcloud Talk application
-  ~
-  ~ @author Mario Danic
-  ~ Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
-  ~
-  ~ This program is free software: you can redistribute it and/or modify
-  ~ it under the terms of the GNU General Public License as published by
-  ~ the Free Software Foundation, either version 3 of the License, or
-  ~ at your option) any later version.
-  ~
-  ~ This program is distributed in the hope that it will be useful,
-  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
-  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  ~ GNU General Public License for more details.
-  ~
-  ~ You should have received a copy of the GNU General Public License
-  ~ along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  -->
-
-<vector android:autoMirrored="true" android:height="24dp"
-    android:viewportHeight="24.0" android:viewportWidth="24.0"
-    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
-    <path android:fillColor="#FF000000" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/>
-</vector>
diff --git a/app/src/main/res/drawable/ic_public_black_24px.xml b/app/src/main/res/drawable/ic_public_black_24px.xml
deleted file mode 100644
index 49c84ae8817..00000000000
--- a/app/src/main/res/drawable/ic_public_black_24px.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-  ~ Nextcloud Talk application
-  ~
-  ~ @author Mario Danic
-  ~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
-  ~
-  ~ This program is free software: you can redistribute it and/or modify
-  ~ it under the terms of the GNU General Public License as published by
-  ~ the Free Software Foundation, either version 3 of the License, or
-  ~ at your option) any later version.
-  ~
-  ~ This program is distributed in the hope that it will be useful,
-  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
-  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  ~ GNU General Public License for more details.
-  ~
-  ~ You should have received a copy of the GNU General Public License
-  ~ along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  -->
-
-<vector android:autoMirrored="true" android:height="24dp"
-    android:viewportHeight="16.0" android:viewportWidth="16.0"
-    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
-    <path android:fillColor="#FF000000" android:pathData="m9.236,2.166 l-3.182,3.184c-0.707,0.707 -1.038,1.618 -0.988,2.457 0.05,0.839 0.433,1.584 0.988,2.139l1.412,-1.416c-0.567,-0.567 -0.544,-1.219 0.002,-1.766l3.181,-3.182c0.525,-0.525 1.251,-0.523 1.772,-0.002 0.482,0.556 0.527,1.238 -0.004,1.77l-0.82,0.82c0.555,0.785 0.645,1.366 0.593,2.234l1.641,-1.641c1.237,-1.237 1.237,-3.365 0,-4.602 -1.236,-1.236 -3.342,-1.211 -4.596,0.004zM9.943,6.051 L8.529,7.469c0,0 0.003,0 0.004,0 0.55,0.55 0.507,1.258 -0.004,1.77l-3.182,3.182c-0.696,0.592 -1.298,0.471 -1.77,0 -0.626,-0.626 -0.5,-1.268 0,-1.768l0.85,-0.847c-0.556,-0.784 -0.648,-1.365 -0.598,-2.232l-1.666,1.666c-1.239,1.239 -1.236,3.36 0,4.596 1.235,1.235 3.362,1.236 4.598,0l3.182,-3.182c0.709,-0.708 1.04,-1.618 0.991,-2.459 -0.048,-0.84 -0.432,-1.586 -0.989,-2.141z"/>
-</vector>
diff --git a/app/src/main/res/layout/activity_contacts.xml b/app/src/main/res/layout/activity_contacts.xml
index 6d7d87207a7..f318fce3026 100644
--- a/app/src/main/res/layout/activity_contacts.xml
+++ b/app/src/main/res/layout/activity_contacts.xml
@@ -93,7 +93,7 @@
         android:orientation="vertical">
 
         <RelativeLayout
-            android:id="@+id/initial_relative_layout"
+            android:id="@+id/public_conversation_create"
             android:layout_width="match_parent"
             android:layout_height="wrap_content">
 
@@ -124,7 +124,7 @@
         </RelativeLayout>
 
         <RelativeLayout
-            android:id="@+id/secondary_relative_layout"
+            android:id="@+id/public_conversation_info"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_centerInParent="true"
@@ -178,40 +178,6 @@
             android:textAppearance="@style/ListItem" />
     </RelativeLayout>
 
-    <RelativeLayout
-        android:id="@+id/join_conversation_via_link"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="@dimen/standard_margin"
-        android:layout_marginTop="@dimen/standard_half_margin"
-        android:layout_marginEnd="@dimen/standard_margin"
-        android:layout_marginBottom="@dimen/standard_half_margin"
-        android:orientation="vertical">
-
-        <ImageView
-            android:id="@+id/join_conversation_via_link_image"
-            android:layout_width="@dimen/avatar_size"
-            android:layout_height="@dimen/avatar_size"
-            android:layout_centerVertical="true"
-            android:layout_marginEnd="@dimen/standard_margin"
-            android:background="@drawable/round_bgnd"
-            android:contentDescription="@null"
-            android:padding="@dimen/standard_half_padding"
-            android:src="@drawable/ic_public_black_24px"
-            app:tint="@color/white" />
-
-        <TextView
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_centerVertical="true"
-            android:layout_toEndOf="@id/join_conversation_via_link_image"
-            android:ellipsize="middle"
-            android:singleLine="true"
-            android:text="@string/nc_join_via_link"
-            android:textAlignment="viewStart"
-            android:textAppearance="@style/ListItem" />
-    </RelativeLayout>
-
     <include
         android:id="@+id/controller_generic_rv"
         layout="@layout/controller_generic_rv" />
diff --git a/app/src/main/res/layout/activity_conversation_info.xml b/app/src/main/res/layout/activity_conversation_info.xml
index f25f8a84399..f92306cca54 100644
--- a/app/src/main/res/layout/activity_conversation_info.xml
+++ b/app/src/main/res/layout/activity_conversation_info.xml
@@ -75,36 +75,36 @@
             android:orientation="vertical">
 
             <RelativeLayout
-                    android:id="@+id/conversation_info_name"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_marginTop="@dimen/standard_quarter_margin"
-                    android:animateLayoutChanges="true"
-                    android:visibility="gone"
-                    tools:visibility="visible"
-                    android:layout_marginStart="@dimen/standard_margin"
-                    android:layout_marginEnd="@dimen/standard_margin">
+                android:id="@+id/conversation_info_name"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="@dimen/standard_margin"
+                android:layout_marginTop="@dimen/standard_quarter_margin"
+                android:layout_marginEnd="@dimen/standard_margin"
+                android:animateLayoutChanges="true"
+                android:visibility="gone"
+                tools:visibility="visible">
 
-                    <ImageView
-                        android:id="@+id/avatar_image"
-                        android:layout_width="@dimen/avatar_size_big"
-                        android:layout_height="@dimen/avatar_size_big"
-                        android:layout_marginTop="@dimen/standard_margin"
-                        android:layout_centerHorizontal="true"
-                        android:contentDescription="@string/avatar"
-                        tools:src="@drawable/account_circle_48dp" />
-
-                    <androidx.emoji2.widget.EmojiTextView
-                        android:id="@+id/display_name_text"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:layout_below="@id/avatar_image"
-                        android:layout_centerHorizontal="true"
-                        android:layout_marginTop="@dimen/margin_between_elements"
-                        android:textSize="@dimen/headline_text_size"
-                        tools:text="Jane Doe" />
+                <ImageView
+                    android:id="@+id/avatar_image"
+                    android:layout_width="@dimen/avatar_size_big"
+                    android:layout_height="@dimen/avatar_size_big"
+                    android:layout_centerHorizontal="true"
+                    android:layout_marginTop="@dimen/standard_margin"
+                    android:contentDescription="@string/avatar"
+                    tools:src="@drawable/account_circle_48dp" />
+
+                <androidx.emoji2.widget.EmojiTextView
+                    android:id="@+id/display_name_text"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_below="@id/avatar_image"
+                    android:layout_centerHorizontal="true"
+                    android:layout_marginTop="@dimen/margin_between_elements"
+                    android:textSize="@dimen/headline_text_size"
+                    tools:text="Jane Doe" />
 
-                </RelativeLayout>
+            </RelativeLayout>
 
             <LinearLayout
                 android:id="@+id/conversation_description"
@@ -119,43 +119,41 @@
                     android:id="@+id/description_text"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:layout_marginTop="@dimen/standard_half_margin"
-                    android:layout_marginBottom="@dimen/standard_half_margin"
                     android:layout_marginStart="@dimen/standard_margin"
+                    android:layout_marginTop="@dimen/standard_half_margin"
                     android:layout_marginEnd="@dimen/standard_margin"
+                    android:layout_marginBottom="@dimen/standard_half_margin"
                     android:autoLink="web"
                     tools:text="Hello world!" />
             </LinearLayout>
 
             <LinearLayout
-                    android:id="@+id/add_to_favorites_button"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_marginTop="@dimen/standard_quarter_margin"
-                    android:orientation="horizontal"
-                    android:padding="@dimen/standard_half_padding"
-                    android:visibility="gone"
-                    tools:visibility="gone">
-
-
-                        <com.google.android.material.button.MaterialButton
-                            android:layout_width="wrap_content"
-                            android:layout_height="wrap_content"
-                            android:background="@color/transparent"
-                            app:icon="@drawable/ic_star_black_24dp"
-                            app:iconGravity="textStart"
-                            app:iconSize="@dimen/sm_icon_height"
-                            app:iconTint="@color/grey_600" />
+                android:id="@+id/add_to_favorites_button"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/standard_quarter_margin"
+                android:orientation="horizontal"
+                android:padding="@dimen/standard_half_padding"
+                android:visibility="gone"
+                tools:visibility="gone">
 
-                        <com.google.android.material.textview.MaterialTextView
-                            android:layout_width="wrap_content"
-                            android:layout_height="match_parent"
-                            android:gravity="center_vertical"
-                            android:text="@string/nc_add_to_favorites"
-                            android:textSize="@dimen/two_line_primary_text_size" />
+                <com.google.android.material.button.MaterialButton
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:background="@color/transparent"
+                    app:icon="@drawable/ic_star_black_24dp"
+                    app:iconGravity="textStart"
+                    app:iconSize="@dimen/sm_icon_height"
+                    app:iconTint="@color/grey_600" />
 
+                <com.google.android.material.textview.MaterialTextView
+                    android:layout_width="wrap_content"
+                    android:layout_height="match_parent"
+                    android:gravity="center_vertical"
+                    android:text="@string/nc_add_to_favorites"
+                    android:textSize="@dimen/two_line_primary_text_size" />
 
-                </LinearLayout>
+            </LinearLayout>
 
             <LinearLayout
                 android:id="@+id/settings"
@@ -187,251 +185,244 @@
             </LinearLayout>
 
             <LinearLayout
-                    android:id="@+id/shared_items"
+                android:id="@+id/shared_items"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/standard_quarter_margin"
+                android:orientation="vertical">
+
+                <com.google.android.material.textview.MaterialTextView
+                    android:id="@+id/shared_items_title"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
-                    android:layout_marginTop="@dimen/standard_quarter_margin"
-                    android:orientation="vertical"
-                    >
+                    android:padding="@dimen/standard_padding"
+                    android:text="@string/nc_shared_items"
+                    android:textSize="@dimen/headline_text_size"
+                    android:textStyle="bold" />
+
+                <LinearLayout
+                    android:id="@+id/shared_items_button"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:background="?android:attr/selectableItemBackground"
+                    android:orientation="horizontal"
+                    android:padding="@dimen/standard_padding">
+
+                    <ImageView
+                        android:layout_width="24dp"
+                        android:layout_height="40dp"
+                        android:layout_marginEnd="@dimen/standard_margin"
+                        android:contentDescription="@null"
+                        android:src="@drawable/ic_folder_multiple_image"
+                        app:tint="@color/grey_600" />
 
                     <com.google.android.material.textview.MaterialTextView
-                        android:id="@+id/shared_items_title"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:text="@string/nc_shared_items"
-                        android:textSize="@dimen/headline_text_size"
-                        android:textStyle="bold"
-                        android:padding="@dimen/standard_padding"/>
-
-                    <LinearLayout
-                            android:id="@+id/shared_items_button"
-                            android:layout_width="match_parent"
-                            android:layout_height="wrap_content"
-                            android:orientation="horizontal"
-                            android:padding="@dimen/standard_padding"
-                            android:background="?android:attr/selectableItemBackground">
-
-                        <ImageView
-                            android:layout_width="24dp"
-                            android:layout_height="40dp"
-                            android:layout_marginEnd="@dimen/standard_margin"
-                            android:contentDescription="@null"
-                            android:src="@drawable/ic_folder_multiple_image"
-                            app:tint="@color/grey_600" />
-
-                                <com.google.android.material.textview.MaterialTextView
-                                    android:layout_width="wrap_content"
-                                    android:layout_height="match_parent"
-                                    android:gravity="center_vertical"
-                                    android:text="@string/nc_shared_items_description"
-                                    android:textSize="@dimen/two_line_primary_text_size" />
-
-                        </LinearLayout>
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:gravity="center_vertical"
+                        android:text="@string/nc_shared_items_description"
+                        android:textSize="@dimen/two_line_primary_text_size" />
+
                 </LinearLayout>
+            </LinearLayout>
 
 
             <LinearLayout
-                    android:id="@+id/conversation_settings"
+                android:id="@+id/conversation_settings"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/standard_quarter_margin"
+                android:orientation="vertical">
+
+                <com.google.android.material.textview.MaterialTextView
+                    android:id="@+id/conversation_settings_title"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
-                    android:layout_marginTop="@dimen/standard_quarter_margin"
-                    android:orientation="vertical"
-                    >
+                    android:padding="@dimen/standard_padding"
+                    android:text="@string/nc_conversation_settings"
+                    android:textSize="@dimen/headline_text_size"
+                    android:textStyle="bold" />
+
+                <com.google.android.material.textfield.TextInputLayout
+                    android:id="@+id/conversation_info_chat_settings_input_layout"
+                    style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginHorizontal="@dimen/standard_margin"
+                    android:layout_marginTop="@dimen/standard_half_margin"
+                    android:hint="@string/nc_expire_messages">
 
-                    <com.google.android.material.textview.MaterialTextView
-                        android:id="@+id/conversation_settings_title"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:text="@string/nc_conversation_settings"
-                        android:textSize="@dimen/headline_text_size"
-                        android:textStyle="bold"
-                        android:padding="@dimen/standard_padding"/>
-
-                    <com.google.android.material.textfield.TextInputLayout
-                        android:id="@+id/conversation_info_chat_settings_input_layout"
-                        style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
+                    <com.google.android.material.textfield.MaterialAutoCompleteTextView
+                        android:id="@+id/conversation_settings_dropdown"
                         android:layout_width="match_parent"
                         android:layout_height="wrap_content"
-                        android:layout_marginTop="@dimen/standard_half_margin"
-                        android:layout_marginHorizontal="@dimen/standard_margin"
-                        android:hint="@string/nc_expire_messages">
+                        android:inputType="none"
+                        android:lines="1"
+                        android:popupTheme="@style/ThemeOverlay.AppTheme.PopupMenu"
+                        android:text="" />
 
-                        <com.google.android.material.textfield.MaterialAutoCompleteTextView
-                            android:id="@+id/conversation_settings_dropdown"
-                            android:layout_width="match_parent"
-                            android:layout_height="wrap_content"
-                            android:inputType="none"
-                            android:lines="1"
-                            android:popupTheme="@style/ThemeOverlay.AppTheme.PopupMenu"
-                            android:text="" />
 
+                </com.google.android.material.textfield.TextInputLayout>
+
+                <com.google.android.material.textview.MaterialTextView
+                    android:id="@+id/conversation_info_expire_messages_explanation"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_margin="@dimen/standard_margin"
+                    android:text="@string/nc_expire_messages_explanation"
+                    android:textColor="@color/disabled_text"
+                    android:textSize="@dimen/supporting_text_text_size" />
+            </LinearLayout>
+
+            <LinearLayout
+                android:id="@+id/participants"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/standard_quarter_margin"
+                android:orientation="vertical"
+                android:visibility="gone"
+                tools:ignore="UnknownIdInLayout"
+                tools:visibility="visible">
+
+                <com.google.android.material.textview.MaterialTextView
+                    android:id="@+id/participants_list_category"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:padding="@dimen/standard_padding"
+                    android:text="@string/nc_participants"
+                    android:textColor="@color/colorPrimary"
+                    android:textSize="@dimen/headline_text_size"
+                    android:textStyle="bold" />
+
+                <LinearLayout
+                    android:id="@+id/addParticipantsAction"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/standard_quarter_margin"
+                    android:background="?android:attr/selectableItemBackground"
+                    android:orientation="horizontal"
+                    android:padding="@dimen/standard_padding">
+
+                    <ImageView
+                        android:layout_width="24dp"
+                        android:layout_height="40dp"
+                        android:layout_marginEnd="@dimen/standard_margin"
+                        android:contentDescription="@null"
+                        android:src="@drawable/ic_account_plus"
+                        app:tint="@color/grey_600" />
 
-                    </com.google.android.material.textfield.TextInputLayout>
 
                     <com.google.android.material.textview.MaterialTextView
-                        android:id="@+id/conversation_info_expire_messages_explanation"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:layout_margin="@dimen/standard_margin"
-                        android:text="@string/nc_expire_messages_explanation"
-                        android:textColor="@color/disabled_text"
-                        android:textSize="@dimen/supporting_text_text_size"/>
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:gravity="center_vertical"
+                        android:text="@string/nc_participants_add"
+                        android:textSize="@dimen/two_line_primary_text_size" />
+
                 </LinearLayout>
 
+                <androidx.recyclerview.widget.RecyclerView
+                    android:id="@+id/recycler_view"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    tools:listitem="@layout/rv_item_conversation_info_participant" />
+            </LinearLayout>
+
             <LinearLayout
-                    android:id="@+id/participants"
+                android:id="@+id/danger_zone_options"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/standard_quarter_margin"
+                android:orientation="vertical">
+
+                <com.google.android.material.textview.MaterialTextView
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:padding="@dimen/standard_padding"
+                    android:text="@string/danger_zone"
+                    android:textColor="@color/design_default_color_error"
+                    android:textSize="@dimen/headline_text_size"
+                    android:textStyle="bold" />
+
+                <LinearLayout
+                    android:id="@+id/leaveConversationAction"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:layout_marginTop="@dimen/standard_quarter_margin"
-                    android:visibility="gone"
-                    tools:ignore="UnknownIdInLayout"
-                    tools:visibility="visible"
-                    android:orientation="vertical">
+                    android:background="?android:attr/selectableItemBackground"
+                    android:orientation="horizontal"
+                    android:padding="@dimen/standard_padding">
+
+                    <ImageView
+                        android:layout_width="24dp"
+                        android:layout_height="40dp"
+                        android:layout_marginEnd="@dimen/standard_margin"
+                        android:contentDescription="@null"
+                        android:src="@drawable/ic_exit_to_app_black_24dp"
+                        app:tint="@color/design_default_color_error" />
 
                     <com.google.android.material.textview.MaterialTextView
-                        android:id="@+id/participants_list_category"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:padding="@dimen/standard_padding"
-                        android:text="@string/nc_participants"
-                        android:textColor="@color/colorPrimary"
-                        android:textSize="@dimen/headline_text_size"
-                        android:textStyle="bold" />
-
-                    <LinearLayout
-                            android:id="@+id/addParticipantsAction"
-                            android:layout_width="match_parent"
-                            android:layout_height="wrap_content"
-                            android:layout_marginTop="@dimen/standard_quarter_margin"
-                            android:orientation="horizontal"
-                            android:padding="@dimen/standard_padding"
-                            android:background="?android:attr/selectableItemBackground">
-
-                        <ImageView
-                            android:layout_width="24dp"
-                            android:layout_height="40dp"
-                            android:layout_marginEnd="@dimen/standard_margin"
-                            android:contentDescription="@null"
-                            android:src="@drawable/ic_account_plus"
-                            app:tint="@color/grey_600" />
-
-
-                            <com.google.android.material.textview.MaterialTextView
-                                android:layout_width="wrap_content"
-                                android:layout_height="match_parent"
-                                android:gravity="center_vertical"
-                                android:text="@string/nc_participants_add"
-                                android:textSize="@dimen/two_line_primary_text_size" />
-
-                        </LinearLayout>
-
-                    <androidx.recyclerview.widget.RecyclerView
-                        android:id="@+id/recycler_view"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        tools:listitem="@layout/rv_item_conversation_info_participant" />
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:gravity="center_vertical"
+                        android:text="@string/nc_leave"
+                        android:textColor="@color/design_default_color_error"
+                        android:textSize="@dimen/two_line_primary_text_size" />
                 </LinearLayout>
 
-            <LinearLayout
-                    android:id="@+id/danger_zone_options"
+                <LinearLayout
+                    android:id="@+id/clearConversationHistory"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:layout_marginTop="@dimen/standard_quarter_margin"
-                    android:orientation="vertical"
-                    >
+                    android:background="?android:attr/selectableItemBackground"
+                    android:orientation="horizontal"
+                    android:padding="@dimen/standard_padding">
+
+                    <ImageView
+                        android:layout_width="24dp"
+                        android:layout_height="40dp"
+                        android:layout_marginEnd="@dimen/standard_margin"
+                        android:contentDescription="@null"
+                        android:src="@drawable/ic_delete_black_24dp"
+                        app:tint="@color/design_default_color_error" />
 
                     <com.google.android.material.textview.MaterialTextView
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:text="@string/danger_zone"
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:gravity="center_vertical"
+                        android:text="@string/nc_clear_history"
+                        android:textColor="@color/design_default_color_error"
+                        android:textSize="@dimen/two_line_primary_text_size" />
+                </LinearLayout>
+
+                <LinearLayout
+                    android:id="@+id/deleteConversationAction"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/standard_quarter_margin"
+                    android:background="?android:attr/selectableItemBackground"
+                    android:orientation="horizontal"
+                    android:padding="@dimen/standard_padding">
+
+                    <ImageView
+                        android:layout_width="24dp"
+                        android:layout_height="40dp"
+                        android:layout_marginEnd="@dimen/standard_margin"
+                        android:contentDescription="@null"
+                        android:src="@drawable/ic_delete_black_24dp"
+                        app:tint="@color/design_default_color_error" />
+
+                    <com.google.android.material.textview.MaterialTextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:gravity="center_vertical"
+                        android:text="@string/nc_delete_call"
                         android:textColor="@color/design_default_color_error"
-                        android:textSize="@dimen/headline_text_size"
-                        android:textStyle="bold"
-                        android:padding="@dimen/standard_padding"/>
-
-                    <LinearLayout
-                            android:id="@+id/leaveConversationAction"
-                            android:layout_width="match_parent"
-                            android:layout_height="wrap_content"
-                            android:layout_marginTop="@dimen/standard_quarter_margin"
-                            android:orientation="horizontal"
-                            android:padding="@dimen/standard_padding"
-                            android:background="?android:attr/selectableItemBackground">
-
-                        <ImageView
-                            android:layout_width="24dp"
-                            android:layout_height="40dp"
-                            android:layout_marginEnd="@dimen/standard_margin"
-                            android:contentDescription="@null"
-                            android:src="@drawable/ic_exit_to_app_black_24dp"
-                            app:tint="@color/design_default_color_error" />
-
-                        <com.google.android.material.textview.MaterialTextView
-                            android:layout_width="wrap_content"
-                            android:layout_height="match_parent"
-                            android:gravity="center_vertical"
-                            android:text="@string/nc_leave"
-                            android:textColor="@color/design_default_color_error"
-                            android:textSize="@dimen/two_line_primary_text_size" />
-
-
-
-
-                    </LinearLayout>
-
-                    <LinearLayout
-                            android:id="@+id/clearConversationHistory"
-                            android:layout_width="match_parent"
-                            android:layout_height="wrap_content"
-                            android:layout_marginTop="@dimen/standard_quarter_margin"
-                            android:orientation="horizontal"
-                            android:padding="@dimen/standard_padding"
-                            android:background="?android:attr/selectableItemBackground">
-
-                        <ImageView
-                            android:layout_width="24dp"
-                            android:layout_height="40dp"
-                            android:layout_marginEnd="@dimen/standard_margin"
-                            android:contentDescription="@null"
-                            android:src="@drawable/ic_delete_black_24dp"
-                            app:tint="@color/design_default_color_error" />
-
-                        <com.google.android.material.textview.MaterialTextView
-                            android:layout_width="wrap_content"
-                            android:layout_height="match_parent"
-                            android:gravity="center_vertical"
-                            android:text="@string/nc_clear_history"
-                            android:textColor="@color/design_default_color_error"
-                            android:textSize="@dimen/two_line_primary_text_size" />
-                    </LinearLayout>
-
-                    <LinearLayout
-                            android:id="@+id/deleteConversationAction"
-                            android:layout_width="match_parent"
-                            android:layout_height="wrap_content"
-                            android:layout_marginTop="@dimen/standard_quarter_margin"
-                            android:orientation="horizontal"
-                            android:padding="@dimen/standard_padding"
-                            android:background="?android:attr/selectableItemBackground">
-
-                        <ImageView
-                            android:layout_width="24dp"
-                            android:layout_height="40dp"
-                            android:layout_marginEnd="@dimen/standard_margin"
-                            android:contentDescription="@null"
-                            android:src="@drawable/ic_delete_black_24dp"
-                            app:tint="@color/design_default_color_error" />
-
-                        <com.google.android.material.textview.MaterialTextView
-                            android:layout_width="wrap_content"
-                            android:layout_height="match_parent"
-                            android:gravity="center_vertical"
-                            android:text="@string/nc_delete_call"
-                            android:textColor="@color/design_default_color_error"
-                            android:textSize="@dimen/two_line_primary_text_size" />
-
-                    </LinearLayout>
+                        android:textSize="@dimen/two_line_primary_text_size" />
+
                 </LinearLayout>
+            </LinearLayout>
         </LinearLayout>
     </ScrollView>
 </LinearLayout>
diff --git a/app/src/main/res/layout/controller_operations_menu.xml b/app/src/main/res/layout/controller_operations_menu.xml
deleted file mode 100644
index b5e63641908..00000000000
--- a/app/src/main/res/layout/controller_operations_menu.xml
+++ /dev/null
@@ -1,93 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-  ~ Nextcloud Talk application
-  ~
-  ~ @author Mario Danic
-  ~ Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
-  ~
-  ~ This program is free software: you can redistribute it and/or modify
-  ~ it under the terms of the GNU General Public License as published by
-  ~ the Free Software Foundation, either version 3 of the License, or
-  ~ at your option) any later version.
-  ~
-  ~ This program is distributed in the hope that it will be useful,
-  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
-  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  ~ GNU General Public License for more details.
-  ~
-  ~ You should have received a copy of the GNU General Public License
-  ~ along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  -->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/controller_operations_view"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content">
-
-    <ImageView
-        android:id="@+id/result_image_view"
-        android:layout_width="48dp"
-        android:layout_height="48dp"
-        android:layout_centerHorizontal="true"
-        android:layout_marginStart="24dp"
-        android:layout_marginTop="24dp"
-        android:layout_marginEnd="24dp"
-        android:layout_marginBottom="8dp"
-        android:contentDescription="@null"
-        android:tintMode="src_in"
-        android:visibility="gone" />
-
-    <ProgressBar
-        android:id="@+id/progress_bar"
-        android:layout_width="48dp"
-        android:layout_height="48dp"
-        android:layout_centerInParent="true"
-        android:layout_marginTop="24dp"
-        android:layout_marginBottom="24dp"
-        android:indeterminate="true"
-        android:indeterminateTint="@color/colorPrimary"
-        android:indeterminateTintMode="src_in"
-        android:keepScreenOn="true" />
-
-    <TextView
-        android:id="@+id/result_text_view"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_below="@id/result_image_view"
-        android:layout_centerHorizontal="true"
-        android:layout_marginStart="24dp"
-        android:layout_marginEnd="24dp"
-        android:layout_marginBottom="12dp"
-        android:maxLines="3"
-        android:textAlignment="center"
-        android:textColor="@color/colorPrimary"
-        android:visibility="gone" />
-
-    <com.google.android.material.button.MaterialButton
-        android:id="@+id/ok_button"
-        style="@style/Widget.MaterialComponents.Button.TextButton"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_below="@id/result_text_view"
-        android:layout_alignParentEnd="true"
-        android:layout_marginEnd="8dp"
-        android:layout_marginBottom="12dp"
-        android:background="@color/bg_inverse"
-        android:text="@string/nc_ok"
-        android:textColor="@color/colorPrimary"
-        android:visibility="gone" />
-
-    <com.google.android.material.button.MaterialButton
-        android:id="@+id/web_button"
-        style="@style/Widget.MaterialComponents.Button.TextButton"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_below="@id/result_text_view"
-        android:layout_marginEnd="8dp"
-        android:layout_marginBottom="12dp"
-        android:layout_toStartOf="@id/ok_button"
-        android:background="@color/bg_inverse"
-        android:text="@string/nc_join_via_web"
-        android:textColor="@color/nc_darkGreen"
-        android:visibility="gone" />
-
-</RelativeLayout>
diff --git a/app/src/main/res/layout/dialog_bottom_contacts.xml b/app/src/main/res/layout/dialog_bottom_contacts.xml
deleted file mode 100644
index cbccc2e9300..00000000000
--- a/app/src/main/res/layout/dialog_bottom_contacts.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Nextcloud Talk application
-  ~
-  ~ @author Marcel Hibbe
-  ~ @author Andy Scherzinger
-  ~ Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
-  ~ Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
-  ~
-  ~ This program is free software: you can redistribute it and/or modify
-  ~ it under the terms of the GNU General Public License as published by
-  ~ the Free Software Foundation, either version 3 of the License, or
-  ~ at your option) any later version.
-  ~
-  ~ This program is distributed in the hope that it will be useful,
-  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
-  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  ~ GNU General Public License for more details.
-  ~
-  ~ You should have received a copy of the GNU General Public License
-  ~ along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical"
-    android:paddingStart="@dimen/standard_padding"
-    android:paddingEnd="@dimen/standard_padding"
-    android:paddingBottom="@dimen/standard_half_padding">
-
-</LinearLayout>
diff --git a/app/src/main/res/layout/dialog_conversation_operations.xml b/app/src/main/res/layout/dialog_conversation_operations.xml
index 7e05f329fac..65df06d174a 100644
--- a/app/src/main/res/layout/dialog_conversation_operations.xml
+++ b/app/src/main/res/layout/dialog_conversation_operations.xml
@@ -47,7 +47,7 @@
             tools:text="conversation name" />
 
         <LinearLayout
-            android:id="@+id/conversation_operation_remove_favorite"
+            android:id="@+id/conversation_remove_from_favorites"
             android:layout_width="match_parent"
             android:layout_height="@dimen/bottom_sheet_item_height"
             android:background="?android:attr/selectableItemBackground"
@@ -77,7 +77,7 @@
         </LinearLayout>
 
         <LinearLayout
-            android:id="@+id/conversation_operation_add_favorite"
+            android:id="@+id/conversation_add_to_favorites"
             android:layout_width="match_parent"
             android:layout_height="@dimen/bottom_sheet_item_height"
             android:background="?android:attr/selectableItemBackground"
@@ -107,7 +107,7 @@
         </LinearLayout>
 
         <LinearLayout
-            android:id="@+id/conversation_operation_mark_as_read"
+            android:id="@+id/conversation_mark_as_read"
             android:layout_width="match_parent"
             android:layout_height="@dimen/bottom_sheet_item_height"
             android:background="?android:attr/selectableItemBackground"
@@ -137,7 +137,7 @@
         </LinearLayout>
 
         <LinearLayout
-            android:id="@+id/conversation_operation_mark_as_unread"
+            android:id="@+id/conversation_mark_as_unread"
             android:layout_width="match_parent"
             android:layout_height="@dimen/bottom_sheet_item_height"
             android:background="?android:attr/selectableItemBackground"
diff --git a/app/src/main/res/layout/controller_entry_menu.xml b/app/src/main/res/layout/dialog_create_conversation.xml
similarity index 79%
rename from app/src/main/res/layout/controller_entry_menu.xml
rename to app/src/main/res/layout/dialog_create_conversation.xml
index 4c851cc3f0c..6aafea7c235 100644
--- a/app/src/main/res/layout/controller_entry_menu.xml
+++ b/app/src/main/res/layout/dialog_create_conversation.xml
@@ -27,22 +27,6 @@
     android:paddingTop="@dimen/standard_padding"
     android:paddingEnd="@dimen/standard_half_padding">
 
-    <com.google.android.material.button.MaterialButton
-        android:id="@+id/ok_button"
-        style="@style/Widget.MaterialComponents.Button.TextButton"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_below="@id/text_input_layout"
-        android:layout_alignParentEnd="true"
-        android:layout_marginTop="@dimen/standard_half_margin"
-        android:layout_marginBottom="@dimen/standard_half_margin"
-        android:alpha="0.7"
-        android:background="@color/bg_default"
-        android:enabled="false"
-        android:text="@string/nc_proceed"
-        android:textAllCaps="false"
-        android:textColor="@color/colorPrimary" />
-
     <com.google.android.material.textfield.TextInputLayout
         android:id="@+id/text_input_layout"
         style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
@@ -77,7 +61,6 @@
         android:background="@color/transparent"
         android:contentDescription="@string/nc_add_emojis"
         android:src="@drawable/ic_insert_emoticon_black_24dp"
-        android:visibility="gone"
         app:tint="@color/medium_emphasis_text"
         tools:visibility="visible" />
 
diff --git a/app/src/main/res/layout/dialog_rename_conversation.xml b/app/src/main/res/layout/dialog_rename_conversation.xml
new file mode 100644
index 00000000000..27ed22aca4d
--- /dev/null
+++ b/app/src/main/res/layout/dialog_rename_conversation.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Nextcloud Talk application
+  ~
+  ~ @author Mario Danic
+  ~ @author Marcel Hibbe
+  ~ Copyright (C) 2023 Marcel Hibbe <dev@mhibbe.de>
+  ~ Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
+  ~
+  ~ This program is free software: you can redistribute it and/or modify
+  ~ it under the terms of the GNU General Public License as published by
+  ~ the Free Software Foundation, either version 3 of the License, or
+  ~ at your option) any later version.
+  ~
+  ~ This program is distributed in the hope that it will be useful,
+  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  ~ GNU General Public License for more details.
+  ~
+  ~ You should have received a copy of the GNU General Public License
+  ~ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingStart="@dimen/standard_padding"
+    android:paddingTop="@dimen/standard_padding"
+    android:paddingEnd="@dimen/standard_half_padding">
+
+    <com.google.android.material.textfield.TextInputLayout
+        android:id="@+id/text_input_layout"
+        style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="@dimen/standard_half_margin"
+        android:layout_toStartOf="@id/smileyButton"
+        app:errorTextAppearance="@style/ErrorAppearance"
+        app:passwordToggleTint="@color/grey_600"
+        app:boxStrokeColor="@color/colorPrimary"
+        app:hintTextColor="@color/colorPrimary">
+
+        <com.nextcloud.talk.utils.EmojiTextInputEditText
+            android:id="@+id/text_edit"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:imeOptions="actionDone"
+            android:inputType="textUri"
+            android:singleLine="true"
+            android:textAlignment="viewStart"
+            android:textColor="@color/high_emphasis_text" />
+
+    </com.google.android.material.textfield.TextInputLayout>
+
+    <ImageButton
+        android:id="@+id/smileyButton"
+        android:layout_width="48dp"
+        android:layout_height="match_parent"
+        android:layout_alignBottom="@id/text_input_layout"
+        android:layout_alignParentEnd="true"
+        android:layout_marginStart="-4dp"
+        android:background="@color/transparent"
+        android:contentDescription="@string/nc_add_emojis"
+        android:src="@drawable/ic_insert_emoticon_black_24dp"
+        app:tint="@color/medium_emphasis_text"
+        tools:visibility="visible" />
+
+</RelativeLayout>
diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml
index 4d64f32ef71..7a1e8a6b85d 100644
--- a/app/src/main/res/values-night/colors.xml
+++ b/app/src/main/res/values-night/colors.xml
@@ -44,7 +44,6 @@
 
     <color name="bg_default">#121212</color>
     <color name="bg_default_semitransparent">#99121212</color>
-    <color name="bg_inverse">@color/grey950</color>
 
     <color name="fg_default">#FFFFFF</color>
     <color name="fg_inverse">#121212</color>
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 2a33bdb2a2a..5d7ec0cf371 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -74,7 +74,6 @@
 
     <color name="bg_default">#FFFFFF</color>
     <color name="bg_default_semitransparent">#99FFFFFF</color>
-    <color name="bg_inverse">@color/grey950</color>
     <color name="bg_dark_mention_chips">#333333</color>
 
     <color name="bg_message_list_incoming_bubble">#EFEFEF</color>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 8fa0ef657e9..07e9ef70f7d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -49,6 +49,8 @@ How to translate with transifex:
     <string name="nc_common_set">Set</string>
     <string name="nc_common_dismiss">Dismiss</string>
     <string name="nc_common_error_sorry">Sorry, something went wrong!</string>
+    <string name="nc_common_create">Create</string>
+
 
     <!-- Bottom Navigation -->
     <string name="nc_settings">Settings</string>
@@ -168,10 +170,6 @@ How to translate with transifex:
     <string name="nc_cancel">Cancel</string>
 
     <string name="nc_no_proxy">No proxy</string>
-    <string name="nc_password">Password</string>
-    <string name="nc_conversation_link">Conversation link</string>
-    <string name="nc_new_password">New password</string>
-    <string name="nc_wrong_password">Wrong password</string>
     <string name="nc_about">About</string>
     <string name="nc_privacy">Privacy</string>
     <string name="nc_get_source_code">Get source code</string>
@@ -190,20 +188,27 @@ How to translate with transifex:
     <string name="nc_clear_history_warning">Do you really want to delete all messages in this conversation?</string>
     <string name="nc_clear_history_success">All messages were deleted</string>
     <string name="nc_rename">Rename conversation</string>
+    <string name="nc_rename_confirm">Rename</string>
     <string name="nc_delete_call">Delete conversation</string>
     <string name="nc_delete">Delete</string>
     <string name="nc_delete_all">Delete all</string>
     <string name="nc_delete_conversation_more">If you delete the conversation, it will also be deleted for all other participants.</string>
 
     <string name="nc_new_conversation">New conversation</string>
-    <string name="nc_join_via_link">Join with a link</string>
     <string name="nc_list_open_conversations">List open conversations</string>
-    <string name="nc_join_via_web">Join via web</string>
     <string name="nc_mark_as_read">Mark as read</string>
     <string name="nc_mark_as_unread">Mark as unread</string>
     <string name="nc_add_to_favorites">Add to favorites</string>
     <string name="nc_remove_from_favorites">Remove from favorites</string>
 
+    <string name="added_to_favorites">Added conversation %1$s to favorites</string>
+    <string name="removed_from_favorites">Removed conversation %1$s from favorites</string>
+    <string name="marked_as_unread">Marked conversation %1$s as unread</string>
+    <string name="marked_as_read">Marked conversation %1$s as read</string>
+    <string name="deleted_conversation">Deleted conversation %1$s</string>
+    <string name="left_conversation">You left the conversation %1$s</string>
+    <string name="renamed_conversation">Conversation %1$s was renamed</string>
+
     <string name="nc_forward_to_three_dots">Forward to …</string>
 
     <!-- Open conversations -->
@@ -279,16 +284,10 @@ How to translate with transifex:
     <string name="nc_important_conversation">Important conversation</string>
     <string name="nc_important_conversation_desc">Notifications in this conversation will override Do Not Disturb settings</string>
 
-    <!-- Bottom sheet menu -->
-    <string name="nc_failed_to_perform_operation">Sorry, something went wrong!</string>
-    <string name="nc_failed_signaling_settings">Target server does not support joining public conversations via mobile phones. You may attempt to join the conversation via web browser.</string>
     <string name="nc_all_ok_operation">OK, all done!</string>
     <string name="nc_ok">OK</string>
     <string name="nc_call_name">Conversation name</string>
-    <string name="nc_proceed">Proceed</string>
     <string name="nc_add_emojis">Add emojis</string>
-    <string name="nc_call_name_is_same">The name you entered is the same as the existing one</string>
-    <string name="nc_wrong_link">Conversation link is not valid</string>
     <string name="nc_share_text">Join the conversation at %1$s/index.php/call/%2$s</string>
     <string name="nc_share_subject">%1$s invitation</string>
     <string name="nc_share_text_pass">\nPassword: %1$s</string>