فهرست منبع

Merge pull request #2915 from nextcloud/refactoring/noid/convInfoAndContactsRemoveConductor

Replace Controller with Activity for conversationInfo and contacts
Marcel Hibbe 2 سال پیش
والد
کامیت
c5d97175d7

+ 8 - 0
app/src/main/AndroidManifest.xml

@@ -210,6 +210,14 @@
             android:name=".settings.SettingsActivity"
             android:theme="@style/AppTheme" />
 
+        <activity
+            android:name=".conversation.info.ConversationInfoActivity"
+            android:theme="@style/AppTheme" />
+
+        <activity
+            android:name=".contacts.ContactsActivity"
+            android:theme="@style/AppTheme" />
+
         <receiver android:name=".receivers.PackageReplacedReceiver"
             android:exported="false">
             <intent-filter>

+ 13 - 0
app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt

@@ -93,6 +93,19 @@ class MainActivity : BaseActivity(), ActionBarProvider {
 
         router = Conductor.attachRouter(this, binding.controllerContainer, savedInstanceState)
 
+        if (intent.getBooleanExtra(BundleKeys.KEY_OPEN_CHAT, false)) {
+            logRouterBackStack(router!!)
+            remapChatController(
+                router!!,
+                intent.getParcelableExtra<User>(KEY_USER_ENTITY)!!.id!!,
+                intent.getStringExtra(KEY_ROOM_TOKEN)!!,
+                intent.extras!!,
+                true,
+                true
+            )
+            logRouterBackStack(router!!)
+        }
+
         if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) {
             onNewIntent(intent)
         } else if (!router!!.hasRootController()) {

+ 180 - 156
app/src/main/java/com/nextcloud/talk/controllers/ContactsController.kt → app/src/main/java/com/nextcloud/talk/contacts/ContactsActivity.kt

@@ -21,17 +21,18 @@
  * 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
+package com.nextcloud.talk.contacts
 
 import android.app.SearchManager
 import android.content.Context
+import android.content.Intent
 import android.graphics.PorterDuff
+import android.graphics.drawable.ColorDrawable
 import android.os.Build
 import android.os.Bundle
 import android.text.InputType
 import android.util.Log
 import android.view.Menu
-import android.view.MenuInflater
 import android.view.MenuItem
 import android.view.View
 import android.view.inputmethod.EditorInfo
@@ -44,14 +45,13 @@ import androidx.work.WorkManager
 import autodagger.AutoInjector
 import com.bluelinelabs.logansquare.LoganSquare
 import com.nextcloud.talk.R
+import com.nextcloud.talk.activities.BaseActivity
+import com.nextcloud.talk.activities.MainActivity
 import com.nextcloud.talk.adapters.items.ContactItem
 import com.nextcloud.talk.adapters.items.GenericTextHeaderItem
 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.bottomsheet.ConversationOperationEnum
-import com.nextcloud.talk.controllers.util.viewBinding
 import com.nextcloud.talk.data.user.model.User
 import com.nextcloud.talk.databinding.ControllerContactsRvBinding
 import com.nextcloud.talk.events.OpenConversationEvent
@@ -66,9 +66,10 @@ import com.nextcloud.talk.models.json.participants.Participant
 import com.nextcloud.talk.ui.dialog.ContactsBottomDialog
 import com.nextcloud.talk.users.UserManager
 import com.nextcloud.talk.utils.ApiUtils
+import com.nextcloud.talk.utils.DisplayUtils
 import com.nextcloud.talk.utils.bundle.BundleKeys
+import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_OPEN_CHAT
 import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew
-import com.nextcloud.talk.utils.remapchat.ConductorRemapping
 import eu.davidea.flexibleadapter.FlexibleAdapter
 import eu.davidea.flexibleadapter.SelectableAdapter
 import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
@@ -78,7 +79,6 @@ import io.reactivex.android.schedulers.AndroidSchedulers
 import io.reactivex.disposables.Disposable
 import io.reactivex.schedulers.Schedulers
 import okhttp3.ResponseBody
-import org.greenrobot.eventbus.EventBus
 import org.greenrobot.eventbus.Subscribe
 import org.greenrobot.eventbus.ThreadMode
 import org.parceler.Parcels
@@ -88,18 +88,15 @@ import java.util.Locale
 import javax.inject.Inject
 
 @AutoInjector(NextcloudTalkApplication::class)
-class ContactsController(args: Bundle) :
-    BaseController(R.layout.controller_contacts_rv),
+class ContactsActivity :
+    BaseActivity(),
     SearchView.OnQueryTextListener,
     FlexibleAdapter.OnItemClickListener {
-    private val binding: ControllerContactsRvBinding? by viewBinding(ControllerContactsRvBinding::bind)
+    private lateinit var binding: ControllerContactsRvBinding
 
     @Inject
     lateinit var userManager: UserManager
 
-    @Inject
-    lateinit var eventBus: EventBus
-
     @Inject
     lateinit var ncApi: NcApi
 
@@ -126,18 +123,29 @@ class ContactsController(args: Bundle) :
     private var conversationToken: String? = null
     private var contactsBottomDialog: ContactsBottomDialog? = null
 
-    init {
-        setHasOptionsMenu(true)
-        sharedApplication!!.componentApplication.inject(this)
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
+
+        binding = ControllerContactsRvBinding.inflate(layoutInflater)
+        setupActionBar()
+        setupSystemColors()
+        setContentView(binding.root)
+
+        if (savedInstanceState != null) {
+            if (adapter != null) {
+                adapter?.onRestoreInstanceState(savedInstanceState)
+            }
+        }
 
         existingParticipants = ArrayList()
-        if (args.containsKey(BundleKeys.KEY_NEW_CONVERSATION)) {
+        if (intent.hasExtra(BundleKeys.KEY_NEW_CONVERSATION)) {
             isNewConversationView = true
-        } else if (args.containsKey(BundleKeys.KEY_ADD_PARTICIPANTS)) {
+        } else if (intent.hasExtra(BundleKeys.KEY_ADD_PARTICIPANTS)) {
             isAddingParticipantsView = true
-            conversationToken = args.getString(BundleKeys.KEY_TOKEN)
-            if (args.containsKey(BundleKeys.KEY_EXISTING_PARTICIPANTS)) {
-                existingParticipants = args.getStringArrayList(BundleKeys.KEY_EXISTING_PARTICIPANTS)
+            conversationToken = intent.getStringExtra(BundleKeys.KEY_TOKEN)
+            if (intent.hasExtra(BundleKeys.KEY_EXISTING_PARTICIPANTS)) {
+                existingParticipants = intent.getStringArrayListExtra(BundleKeys.KEY_EXISTING_PARTICIPANTS)
             }
         }
         selectedUserIds = HashSet()
@@ -146,34 +154,31 @@ class ContactsController(args: Bundle) :
         selectedCircleIds = HashSet()
     }
 
-    override fun onAttach(view: View) {
-        super.onAttach(view)
-        eventBus.register(this)
+    override fun onResume() {
+        super.onResume()
+
         if (isNewConversationView) {
             toggleConversationPrivacyLayout(!isPublicCall)
         }
         if (isAddingParticipantsView) {
-            binding?.joinConversationViaLink?.joinConversationViaLinkRelativeLayout?.visibility = View.GONE
-            binding?.conversationPrivacyToggle?.callHeaderLayout?.visibility = View.GONE
+            binding.joinConversationViaLink.joinConversationViaLinkRelativeLayout.visibility = View.GONE
+            binding.conversationPrivacyToggle.callHeaderLayout.visibility = View.GONE
         } else {
-            binding?.joinConversationViaLink?.joinConversationViaLinkRelativeLayout?.setOnClickListener {
+            binding.joinConversationViaLink.joinConversationViaLinkRelativeLayout.setOnClickListener {
                 joinConversationViaLink()
             }
-            binding?.conversationPrivacyToggle?.callHeaderLayout?.setOnClickListener {
+            binding.conversationPrivacyToggle.callHeaderLayout.setOnClickListener {
                 toggleCallHeader()
             }
         }
-    }
 
-    override fun onViewBound(view: View) {
-        super.onViewBound(view)
         currentUser = userManager.currentUser.blockingGet()
         if (currentUser != null) {
             credentials = ApiUtils.getCredentials(currentUser!!.username, currentUser!!.token)
         }
         if (adapter == null) {
             contactItems = ArrayList<AbstractFlexibleItem<*>>()
-            adapter = FlexibleAdapter(contactItems, activity, false)
+            adapter = FlexibleAdapter(contactItems, this, false)
             if (currentUser != null) {
                 fetchData()
             }
@@ -182,6 +187,91 @@ class ContactsController(args: Bundle) :
         prepareViews()
     }
 
+    private fun setupActionBar() {
+        setSupportActionBar(binding.contactsToolbar)
+        binding.contactsToolbar.setNavigationOnClickListener {
+            onBackPressed()
+        }
+        supportActionBar?.setDisplayHomeAsUpEnabled(true)
+        supportActionBar?.setDisplayShowHomeEnabled(true)
+        supportActionBar?.setIcon(ColorDrawable(resources!!.getColor(android.R.color.transparent)))
+        supportActionBar?.title = when {
+            isAddingParticipantsView -> {
+                resources!!.getString(R.string.nc_add_participants)
+            }
+            isNewConversationView -> {
+                resources!!.getString(R.string.nc_select_participants)
+            }
+            else -> {
+                resources!!.getString(R.string.nc_app_product_name)
+            }
+        }
+    }
+
+    private fun setupSystemColors() {
+        DisplayUtils.applyColorToStatusBar(
+            this,
+            ResourcesCompat.getColor(
+                resources,
+                R.color.appbar,
+                null
+            )
+        )
+        DisplayUtils.applyColorToNavigationBar(
+            this.window,
+            ResourcesCompat.getColor(resources, R.color.bg_default, null)
+        )
+    }
+
+    override fun onSaveInstanceState(bundle: Bundle) {
+        super.onSaveInstanceState(bundle)
+        adapter?.onSaveInstanceState(bundle)
+    }
+
+    override fun onCreateOptionsMenu(menu: Menu): Boolean {
+        super.onCreateOptionsMenu(menu)
+        menuInflater.inflate(R.menu.menu_contacts, menu)
+        searchItem = menu.findItem(R.id.action_search)
+        doneMenuItem = menu.findItem(R.id.contacts_selection_done)
+        initSearchView()
+        return true
+    }
+
+    override fun onPrepareOptionsMenu(menu: Menu): Boolean {
+        super.onPrepareOptionsMenu(menu)
+        if (searchItem != null) {
+            binding?.titleTextView?.let {
+                viewThemeUtils.platform.colorToolbarMenuIcon(
+                    it.context,
+                    searchItem!!
+                )
+            }
+        }
+
+        checkAndHandleDoneMenuItem()
+        if (adapter?.hasFilter() == true) {
+            searchItem!!.expandActionView()
+            searchView!!.setQuery(adapter!!.getFilter(String::class.java) as CharSequence, false)
+        }
+        return true
+    }
+
+    override fun onOptionsItemSelected(item: MenuItem): Boolean {
+        return when (item.itemId) {
+            R.id.home -> {
+                finish()
+                true
+            }
+            R.id.contacts_selection_done -> {
+                selectionDone()
+                true
+            }
+            else -> {
+                super.onOptionsItemSelected(item)
+            }
+        }
+    }
+
     private fun setupAdapter() {
         adapter?.setNotifyChangeOfUnfilteredItems(true)?.mode = SelectableAdapter.Mode.MULTI
         adapter?.setStickyHeaderElevation(HEADER_ELEVATION)
@@ -285,13 +375,13 @@ class ContactsController(args: Bundle) :
                                     BundleKeys.KEY_ACTIVE_CONVERSATION,
                                     Parcels.wrap(roomOverall.ocs!!.data!!)
                                 )
-                                ConductorRemapping.remapChatController(
-                                    router,
-                                    currentUser!!.id!!,
-                                    roomOverall.ocs!!.data!!.token!!,
-                                    bundle,
-                                    true
-                                )
+
+                                // TODO: go directly to ChatActivity when conductor is removed
+                                bundle.putBoolean(KEY_OPEN_CHAT, true)
+                                val intent = Intent(context, MainActivity::class.java)
+                                intent.putExtras(bundle)
+                                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+                                startActivity(intent)
                             }
 
                             override fun onError(e: Throwable) {
@@ -330,72 +420,28 @@ class ContactsController(args: Bundle) :
             AddParticipantsToConversation::class.java
         ).setInputData(data.build()).build()
         WorkManager.getInstance().enqueue(addParticipantsToConversationWorker)
-        router.popCurrentController()
+        finish()
     }
 
     private fun initSearchView() {
-        if (activity != null) {
-            val searchManager: SearchManager? = activity?.getSystemService(Context.SEARCH_SERVICE) as SearchManager?
-            if (searchItem != null) {
-                searchView = MenuItemCompat.getActionView(searchItem) as SearchView
-                viewThemeUtils.talk.themeSearchView(searchView!!)
-                searchView!!.maxWidth = Int.MAX_VALUE
-                searchView!!.inputType = InputType.TYPE_TEXT_VARIATION_FILTER
-                var imeOptions: Int = EditorInfo.IME_ACTION_DONE or EditorInfo.IME_FLAG_NO_FULLSCREEN
-                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
-                    appPreferences?.isKeyboardIncognito == true
-                ) {
-                    imeOptions = imeOptions or EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING
-                }
-                searchView!!.imeOptions = imeOptions
-                searchView!!.queryHint = resources!!.getString(R.string.nc_search)
-                if (searchManager != null) {
-                    searchView!!.setSearchableInfo(searchManager.getSearchableInfo(activity?.componentName))
-                }
-                searchView!!.setOnQueryTextListener(this)
-            }
-        }
-    }
-
-    override fun onOptionsItemSelected(item: MenuItem): Boolean {
-        return when (item.itemId) {
-            R.id.home -> {
-                router.popCurrentController()
-            }
-            R.id.contacts_selection_done -> {
-                selectionDone()
-                true
-            }
-            else -> {
-                super.onOptionsItemSelected(item)
-            }
-        }
-    }
-
-    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
-        super.onCreateOptionsMenu(menu, inflater)
-        inflater.inflate(R.menu.menu_contacts, menu)
-        searchItem = menu.findItem(R.id.action_search)
-        doneMenuItem = menu.findItem(R.id.contacts_selection_done)
-        initSearchView()
-    }
-
-    override fun onPrepareOptionsMenu(menu: Menu) {
-        super.onPrepareOptionsMenu(menu)
-
+        val searchManager: SearchManager? = getSystemService(Context.SEARCH_SERVICE) as SearchManager?
         if (searchItem != null) {
-            binding?.titleTextView?.let {
-                viewThemeUtils.platform.colorToolbarMenuIcon(
-                    it.context,
-                    searchItem!!
-                )
+            searchView = MenuItemCompat.getActionView(searchItem) as SearchView
+            viewThemeUtils.talk.themeSearchView(searchView!!)
+            searchView!!.maxWidth = Int.MAX_VALUE
+            searchView!!.inputType = InputType.TYPE_TEXT_VARIATION_FILTER
+            var imeOptions: Int = EditorInfo.IME_ACTION_DONE or EditorInfo.IME_FLAG_NO_FULLSCREEN
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
+                appPreferences?.isKeyboardIncognito == true
+            ) {
+                imeOptions = imeOptions or EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING
             }
-        }
-
-        checkAndHandleDoneMenuItem()
-        if (adapter?.hasFilter() == true) {
-            searchItem!!.expandActionView()
-            searchView!!.setQuery(adapter!!.getFilter(String::class.java) as CharSequence, false)
+            searchView!!.imeOptions = imeOptions
+            searchView!!.queryHint = resources!!.getString(R.string.nc_search)
+            if (searchManager != null) {
+                searchView!!.setSearchableInfo(searchManager.getSearchableInfo(componentName))
+            }
+            searchView!!.setOnQueryTextListener(this)
         }
     }
 
@@ -626,7 +672,7 @@ class ContactsController(args: Bundle) :
     }
 
     private fun prepareViews() {
-        layoutManager = SmoothScrollLinearLayoutManager(activity)
+        layoutManager = SmoothScrollLinearLayoutManager(this)
         binding?.controllerGenericRv?.recyclerView?.layoutManager = layoutManager
         binding?.controllerGenericRv?.recyclerView?.setHasFixedSize(true)
         binding?.controllerGenericRv?.recyclerView?.adapter = adapter
@@ -671,18 +717,6 @@ class ContactsController(args: Bundle) :
         }
     }
 
-    override fun onSaveViewState(view: View, outState: Bundle) {
-        adapter?.onSaveInstanceState(outState)
-        super.onSaveViewState(view, outState)
-    }
-
-    override fun onRestoreViewState(view: View, savedViewState: Bundle) {
-        super.onRestoreViewState(view, savedViewState)
-        if (adapter != null) {
-            adapter?.onRestoreInstanceState(savedViewState)
-        }
-    }
-
     override fun onDestroy() {
         super.onDestroy()
         dispose(null)
@@ -716,43 +750,35 @@ class ContactsController(args: Bundle) :
         }
     }
 
-    override val title: String
-        get() = when {
-            isAddingParticipantsView -> {
-                resources!!.getString(R.string.nc_add_participants)
-            }
-            isNewConversationView -> {
-                resources!!.getString(R.string.nc_select_participants)
-            }
-            else -> {
-                resources!!.getString(R.string.nc_app_product_name)
-            }
-        }
-
     private fun prepareAndShowBottomSheetWithBundle(bundle: Bundle) {
         // 11: create conversation-enter name for new conversation
         // 10: get&join room when enter link
-        contactsBottomDialog = ContactsBottomDialog(activity!!, bundle)
+        contactsBottomDialog = ContactsBottomDialog(this, bundle)
         contactsBottomDialog?.show()
     }
 
     @Subscribe(threadMode = ThreadMode.MAIN)
     fun onMessageEvent(openConversationEvent: OpenConversationEvent) {
-        ConductorRemapping.remapChatController(
-            router,
-            currentUser!!.id!!,
-            openConversationEvent.conversation!!.token!!,
-            openConversationEvent.bundle!!,
-            true
-        )
+        // ConductorRemapping.remapChatController(
+        //     router,
+        //     currentUser!!.id!!,
+        //     openConversationEvent.conversation!!.token!!,
+        //     openConversationEvent.bundle!!,
+        //     true
+        // )
+
+        // TODO: go directly to ChatActivity when conductor is removed
+
+        var bundle = openConversationEvent.bundle!!
+
+        bundle.putBoolean(KEY_OPEN_CHAT, true)
+        val intent = Intent(context, MainActivity::class.java)
+        intent.putExtras(bundle)
+        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+        startActivity(intent)
         contactsBottomDialog?.dismiss()
     }
 
-    override fun onDetach(view: View) {
-        super.onDetach(view)
-        eventBus.unregister(this)
-    }
-
     override fun onItemClick(view: View, position: Int): Boolean {
         if (adapter?.getItem(position) is ContactItem) {
             if (!isNewConversationView && !isAddingParticipantsView) {
@@ -812,23 +838,21 @@ class ContactsController(args: Bundle) :
                 }
 
                 override fun onNext(roomOverall: RoomOverall) {
-                    if (activity != null) {
-                        val bundle = Bundle()
-                        bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, currentUser)
-                        bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomOverall.ocs!!.data!!.token)
-                        bundle.putString(BundleKeys.KEY_ROOM_ID, roomOverall.ocs!!.data!!.roomId)
-                        bundle.putParcelable(
-                            BundleKeys.KEY_ACTIVE_CONVERSATION,
-                            Parcels.wrap(roomOverall.ocs!!.data!!)
-                        )
-                        ConductorRemapping.remapChatController(
-                            router,
-                            currentUser!!.id!!,
-                            roomOverall.ocs!!.data!!.token!!,
-                            bundle,
-                            true
-                        )
-                    }
+                    val bundle = Bundle()
+                    bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, currentUser)
+                    bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomOverall.ocs!!.data!!.token)
+                    bundle.putString(BundleKeys.KEY_ROOM_ID, roomOverall.ocs!!.data!!.roomId)
+                    bundle.putParcelable(
+                        BundleKeys.KEY_ACTIVE_CONVERSATION,
+                        Parcels.wrap(roomOverall.ocs!!.data!!)
+                    )
+
+                    // TODO: go directly to ChatActivity when conductor is removed
+                    bundle.putBoolean(KEY_OPEN_CHAT, true)
+                    val intent = Intent(context, MainActivity::class.java)
+                    intent.putExtras(bundle)
+                    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+                    startActivity(intent)
                 }
 
                 override fun onError(e: Throwable) {

+ 5 - 5
app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt

@@ -126,6 +126,7 @@ import com.nextcloud.talk.application.NextcloudTalkApplication
 import com.nextcloud.talk.callbacks.MentionAutocompleteCallback
 import com.nextcloud.talk.controllers.base.BaseController
 import com.nextcloud.talk.controllers.util.viewBinding
+import com.nextcloud.talk.conversation.info.ConversationInfoActivity
 import com.nextcloud.talk.data.user.model.User
 import com.nextcloud.talk.databinding.ControllerChatBinding
 import com.nextcloud.talk.events.UserMentionClickEvent
@@ -1778,11 +1779,10 @@ class ChatController(args: Bundle) :
         bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, conversationUser)
         bundle.putString(KEY_ROOM_TOKEN, roomToken)
         bundle.putBoolean(BundleKeys.KEY_ROOM_ONE_TO_ONE, isOneToOneConversation())
-        router.pushController(
-            RouterTransaction.with(ConversationInfoController(bundle))
-                .pushChangeHandler(HorizontalChangeHandler())
-                .popChangeHandler(HorizontalChangeHandler())
-        )
+
+        val intent = Intent(activity, ConversationInfoActivity::class.java)
+        intent.putExtras(bundle)
+        activity!!.startActivity(intent)
     }
 
     private fun setupMentionAutocomplete() {

+ 4 - 8
app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt

@@ -61,7 +61,6 @@ import coil.request.ImageRequest
 import coil.target.Target
 import coil.transform.CircleCropTransformation
 import com.bluelinelabs.conductor.RouterTransaction
-import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
 import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler
 import com.google.android.material.button.MaterialButton
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
@@ -76,6 +75,7 @@ import com.nextcloud.talk.adapters.items.MessagesTextHeaderItem
 import com.nextcloud.talk.api.NcApi
 import com.nextcloud.talk.application.NextcloudTalkApplication
 import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
+import com.nextcloud.talk.contacts.ContactsActivity
 import com.nextcloud.talk.controllers.base.BaseController
 import com.nextcloud.talk.controllers.util.viewBinding
 import com.nextcloud.talk.data.user.model.User
@@ -767,13 +767,9 @@ class ConversationsListController(bundle: Bundle) :
             conversation.type === Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL
 
     private fun showNewConversationsScreen() {
-        val bundle = Bundle()
-        bundle.putBoolean(KEY_NEW_CONVERSATION, true)
-        router.pushController(
-            RouterTransaction.with(ContactsController(bundle))
-                .pushChangeHandler(HorizontalChangeHandler())
-                .popChangeHandler(HorizontalChangeHandler())
-        )
+        val intent = Intent(context, ContactsActivity::class.java)
+        intent.putExtra(KEY_NEW_CONVERSATION, true)
+        startActivity(intent)
     }
 
     private fun dispose(disposable: Disposable?) {

+ 165 - 175
app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt → app/src/main/java/com/nextcloud/talk/conversation/info/ConversationInfoActivity.kt

@@ -5,7 +5,7 @@
  * @author Andy Scherzinger
  * @author Tim Krüger
  * @author Marcel Hibbe
- * Copyright (C) 2022 Marcel Hibbe (dev@mhibbe.de)
+ * Copyright (C) 2022-2023 Marcel Hibbe (dev@mhibbe.de)
  * Copyright (C) 2021-2022 Tim Krüger <t@timkrueger.me>
  * Copyright (C) 2021 Andy Scherzinger (info@andy-scherzinger.de)
  * Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
@@ -24,21 +24,22 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-package com.nextcloud.talk.controllers
+package com.nextcloud.talk.conversation.info
 
 import android.annotation.SuppressLint
 import android.content.Intent
+import android.graphics.drawable.ColorDrawable
 import android.os.Bundle
 import android.os.Parcelable
 import android.text.TextUtils
 import android.util.Log
-import android.view.MenuItem
 import android.view.View
 import android.view.View.GONE
 import android.view.View.VISIBLE
 import android.widget.Toast
 import androidx.appcompat.app.AlertDialog
 import androidx.appcompat.widget.SwitchCompat
+import androidx.core.content.res.ResourcesCompat
 import androidx.work.Data
 import androidx.work.OneTimeWorkRequest
 import androidx.work.WorkManager
@@ -47,18 +48,16 @@ import com.afollestad.materialdialogs.LayoutMode.WRAP_CONTENT
 import com.afollestad.materialdialogs.MaterialDialog
 import com.afollestad.materialdialogs.bottomsheets.BottomSheet
 import com.afollestad.materialdialogs.datetime.dateTimePicker
-import com.bluelinelabs.conductor.RouterTransaction
-import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
 import com.nextcloud.talk.R
+import com.nextcloud.talk.activities.BaseActivity
+import com.nextcloud.talk.activities.MainActivity
 import com.nextcloud.talk.adapters.items.ParticipantItem
 import com.nextcloud.talk.api.NcApi
 import com.nextcloud.talk.application.NextcloudTalkApplication
-import com.nextcloud.talk.controllers.base.BaseController
+import com.nextcloud.talk.contacts.ContactsActivity
 import com.nextcloud.talk.controllers.bottomsheet.items.BasicListItemWithImage
 import com.nextcloud.talk.controllers.bottomsheet.items.listItemsWithImage
-import com.nextcloud.talk.controllers.util.viewBinding
-import com.nextcloud.talk.conversation.info.GuestAccessHelper
 import com.nextcloud.talk.data.user.model.User
 import com.nextcloud.talk.databinding.ControllerConversationInfoBinding
 import com.nextcloud.talk.events.EventStatus
@@ -82,6 +81,7 @@ import com.nextcloud.talk.shareditems.activities.SharedItemsActivity
 import com.nextcloud.talk.utils.ApiUtils
 import com.nextcloud.talk.utils.DateConstants
 import com.nextcloud.talk.utils.DateUtils
+import com.nextcloud.talk.utils.DisplayUtils
 import com.nextcloud.talk.utils.bundle.BundleKeys
 import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew
 import com.nextcloud.talk.utils.preferences.preferencestorage.DatabaseStorageModule
@@ -91,7 +91,6 @@ 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.greenrobot.eventbus.Subscribe
 import org.greenrobot.eventbus.ThreadMode
 import java.util.Calendar
@@ -100,14 +99,11 @@ import java.util.Locale
 import javax.inject.Inject
 
 @AutoInjector(NextcloudTalkApplication::class)
-class ConversationInfoController(args: Bundle) :
-    BaseController(
-        R.layout.controller_conversation_info,
-        args
-    ),
+class ConversationInfoActivity :
+    BaseActivity(),
     FlexibleAdapter.OnItemClickListener {
 
-    private val binding: ControllerConversationInfoBinding? by viewBinding(ControllerConversationInfoBinding::bind)
+    private lateinit var binding: ControllerConversationInfoBinding
 
     @Inject
     lateinit var ncApi: NcApi
@@ -115,16 +111,13 @@ class ConversationInfoController(args: Bundle) :
     @Inject
     lateinit var conversationsRepository: ConversationsRepository
 
-    @Inject
-    lateinit var eventBus: EventBus
-
     @Inject
     lateinit var dateUtils: DateUtils
 
-    private val conversationToken: String?
-    private val conversationUser: User?
-    private val hasAvatarSpacing: Boolean
-    private val credentials: String?
+    private lateinit var conversationToken: String
+    private lateinit var conversationUser: User
+    private var hasAvatarSpacing: Boolean = false
+    private lateinit var credentials: String
     private var roomDisposable: Disposable? = null
     private var participantsDisposable: Disposable? = null
 
@@ -146,68 +139,97 @@ class ConversationInfoController(args: Bundle) :
             return null
         }
 
-    init {
-        setHasOptionsMenu(true)
-        NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this)
-        conversationUser = args.getParcelable(BundleKeys.KEY_USER_ENTITY)
-        conversationToken = args.getString(BundleKeys.KEY_ROOM_TOKEN)
-        hasAvatarSpacing = args.getBoolean(BundleKeys.KEY_ROOM_ONE_TO_ONE, false)
-        credentials = ApiUtils.getCredentials(conversationUser!!.username, conversationUser.token)
-    }
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
 
-    override fun onOptionsItemSelected(item: MenuItem): Boolean {
-        when (item.itemId) {
-            android.R.id.home -> {
-                router.popCurrentController()
-                return true
-            }
-            else -> return super.onOptionsItemSelected(item)
-        }
+        binding = ControllerConversationInfoBinding.inflate(layoutInflater)
+        setupActionBar()
+        setupSystemColors()
+        setContentView(binding.root)
+
+        conversationUser = intent.getParcelableExtra(BundleKeys.KEY_USER_ENTITY)!!
+        conversationToken = intent.getStringExtra(BundleKeys.KEY_ROOM_TOKEN)!!
+        hasAvatarSpacing = intent.getBooleanExtra(BundleKeys.KEY_ROOM_ONE_TO_ONE, false)
+        credentials = ApiUtils.getCredentials(conversationUser.username, conversationUser.token)
     }
 
-    override fun onAttach(view: View) {
-        super.onAttach(view)
-        eventBus.register(this)
+    override fun onResume() {
+        super.onResume()
 
         if (databaseStorageModule == null) {
-            databaseStorageModule = DatabaseStorageModule(conversationUser!!, conversationToken)
+            databaseStorageModule = DatabaseStorageModule(conversationUser, conversationToken)
         }
 
-        binding?.notificationSettingsView?.notificationSettings?.setStorageModule(databaseStorageModule)
-        binding?.webinarInfoView?.webinarSettings?.setStorageModule(databaseStorageModule)
-        binding?.guestAccessView?.guestAccessSettings?.setStorageModule(databaseStorageModule)
+        binding.notificationSettingsView.notificationSettings.setStorageModule(databaseStorageModule)
+        binding.webinarInfoView.webinarSettings.setStorageModule(databaseStorageModule)
+        binding.guestAccessView.guestAccessSettings.setStorageModule(databaseStorageModule)
 
-        binding?.deleteConversationAction?.setOnClickListener { showDeleteConversationDialog() }
-        binding?.leaveConversationAction?.setOnClickListener { leaveConversation() }
-        binding?.clearConversationHistory?.setOnClickListener { showClearHistoryDialog() }
-        binding?.addParticipantsAction?.setOnClickListener { addParticipants() }
+        binding.deleteConversationAction.setOnClickListener { showDeleteConversationDialog() }
+        binding.leaveConversationAction.setOnClickListener { leaveConversation() }
+        binding.clearConversationHistory.setOnClickListener { showClearHistoryDialog() }
+        binding.addParticipantsAction.setOnClickListener { addParticipants() }
 
         if (CapabilitiesUtilNew.hasSpreedFeatureCapability(conversationUser, "rich-object-list-media")) {
-            binding?.showSharedItemsAction?.setOnClickListener { showSharedItems() }
+            binding.showSharedItemsAction.setOnClickListener { showSharedItems() }
         } else {
-            binding?.categorySharedItems?.visibility = GONE
+            binding.categorySharedItems.visibility = GONE
         }
 
         fetchRoomInfo()
 
         themeCategories()
         themeSwitchPreferences()
+
+        binding.addParticipantsAction.visibility = GONE
+
+        binding.progressBar.let { viewThemeUtils.platform.colorCircularProgressBar(it) }
+    }
+
+    private fun setupActionBar() {
+        setSupportActionBar(binding.conversationInfoToolbar)
+        binding.conversationInfoToolbar.setNavigationOnClickListener {
+            onBackPressed()
+        }
+        supportActionBar?.setDisplayHomeAsUpEnabled(true)
+        supportActionBar?.setDisplayShowHomeEnabled(true)
+        supportActionBar?.setIcon(ColorDrawable(resources!!.getColor(android.R.color.transparent)))
+        supportActionBar?.title = if (hasAvatarSpacing) {
+            " " + resources!!.getString(R.string.nc_conversation_menu_conversation_info)
+        } else {
+            resources!!.getString(R.string.nc_conversation_menu_conversation_info)
+        }
+    }
+
+    private fun setupSystemColors() {
+        DisplayUtils.applyColorToStatusBar(
+            this,
+            ResourcesCompat.getColor(
+                resources,
+                R.color.appbar,
+                null
+            )
+        )
+        DisplayUtils.applyColorToNavigationBar(
+            this.window,
+            ResourcesCompat.getColor(resources, R.color.bg_default, null)
+        )
     }
 
     private fun themeSwitchPreferences() {
-        binding?.run {
+        binding.run {
             listOf(
-                binding?.webinarInfoView?.conversationInfoLobby!!,
-                binding?.notificationSettingsView?.callNotifications!!,
-                binding?.notificationSettingsView?.conversationInfoPriorityConversation!!,
-                binding?.guestAccessView?.guestAccessAllowSwitch!!,
-                binding?.guestAccessView?.guestAccessPasswordSwitch!!
+                binding.webinarInfoView.conversationInfoLobby,
+                binding.notificationSettingsView.callNotifications,
+                binding.notificationSettingsView.conversationInfoPriorityConversation,
+                binding.guestAccessView.guestAccessAllowSwitch,
+                binding.guestAccessView.guestAccessPasswordSwitch
             ).forEach(viewThemeUtils.talk::colorSwitchPreference)
         }
     }
 
     private fun themeCategories() {
-        binding?.run {
+        binding.run {
             listOf(
                 conversationInfoName,
                 conversationDescription,
@@ -216,30 +238,22 @@ class ConversationInfoController(args: Bundle) :
                 ownOptions,
                 categorySharedItems,
                 categoryConversationSettings,
-                binding?.guestAccessView?.guestAccessCategory!!,
-                binding?.webinarInfoView?.conversationInfoWebinar!!,
-                binding?.notificationSettingsView?.notificationSettingsCategory!!
+                binding.guestAccessView.guestAccessCategory,
+                binding.webinarInfoView.conversationInfoWebinar,
+                binding.notificationSettingsView.notificationSettingsCategory
             ).forEach(viewThemeUtils.talk::colorPreferenceCategory)
         }
     }
 
     private fun showSharedItems() {
-        val intent = Intent(activity, SharedItemsActivity::class.java)
+        val intent = Intent(this, SharedItemsActivity::class.java)
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
         intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
         intent.putExtra(BundleKeys.KEY_CONVERSATION_NAME, conversation?.displayName)
         intent.putExtra(BundleKeys.KEY_ROOM_TOKEN, conversationToken)
         intent.putExtra(BundleKeys.KEY_USER_ENTITY, conversationUser as Parcelable)
         intent.putExtra(SharedItemsActivity.KEY_USER_IS_OWNER_OR_MODERATOR, conversation?.isParticipantOwnerOrModerator)
-        activity!!.startActivity(intent)
-    }
-
-    override fun onViewBound(view: View) {
-        super.onViewBound(view)
-
-        binding?.addParticipantsAction?.visibility = GONE
-
-        binding?.progressBar?.let { viewThemeUtils.platform.colorCircularProgressBar(it) }
+        startActivity(intent)
     }
 
     private fun setupWebinaryView() {
@@ -257,7 +271,7 @@ class ConversationInfoController(args: Bundle) :
             reconfigureLobbyTimerView()
 
             binding?.webinarInfoView?.startTimePreferences?.setOnClickListener {
-                MaterialDialog(activity!!, BottomSheet(WRAP_CONTENT)).show {
+                MaterialDialog(this, BottomSheet(WRAP_CONTENT)).show {
                     val currentTimeCalendar = Calendar.getInstance()
                     if (conversation!!.lobbyTimer != null && conversation!!.lobbyTimer != 0L) {
                         currentTimeCalendar.timeInMillis = conversation!!.lobbyTimer!! * DateConstants.SECOND_DIVIDER
@@ -345,7 +359,7 @@ class ConversationInfoController(args: Bundle) :
         val apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(ApiUtils.APIv4, 1))
 
         ncApi.setLobbyForConversation(
-            ApiUtils.getCredentials(conversationUser!!.username, conversationUser.token),
+            ApiUtils.getCredentials(conversationUser.username, conversationUser.token),
             ApiUtils.getUrlForRoomWebinaryLobby(apiVersion, conversationUser.baseUrl, conversation!!.token),
             state,
             conversation!!.lobbyTimer
@@ -376,54 +390,45 @@ class ConversationInfoController(args: Bundle) :
         getListOfParticipants()
     }
 
-    override fun onDetach(view: View) {
-        super.onDetach(view)
-        eventBus.unregister(this)
-    }
-
     private fun showDeleteConversationDialog() {
-        if (activity != null) {
-            binding?.conversationInfoName?.let {
-                val dialogBuilder = MaterialAlertDialogBuilder(it.context)
-                    .setIcon(
-                        viewThemeUtils.dialog.colorMaterialAlertDialogIcon(
-                            context,
-                            R.drawable.ic_delete_black_24dp
-                        )
+        binding.conversationInfoName.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()
-                    }
-                    .setNegativeButton(R.string.nc_cancel) { _, _ ->
-                        // unused atm
-                    }
-
-                viewThemeUtils.dialog
-                    .colorMaterialAlertDialogBackground(it.context, dialogBuilder)
-                val dialog = dialogBuilder.show()
-                viewThemeUtils.platform.colorTextButtons(
-                    dialog.getButton(AlertDialog.BUTTON_POSITIVE),
-                    dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
                 )
-            }
+                .setTitle(R.string.nc_delete_call)
+                .setMessage(R.string.nc_delete_conversation_more)
+                .setPositiveButton(R.string.nc_delete) { _, _ ->
+                    deleteConversation()
+                }
+                .setNegativeButton(R.string.nc_cancel) { _, _ ->
+                    // unused atm
+                }
+
+            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 setupAdapter() {
-        if (activity != null) {
-            if (adapter == null) {
-                adapter = FlexibleAdapter(userItems, activity, true)
-            }
-
-            val layoutManager = SmoothScrollLinearLayoutManager(activity)
-            binding?.recyclerView?.layoutManager = layoutManager
-            binding?.recyclerView?.setHasFixedSize(true)
-            binding?.recyclerView?.adapter = adapter
-
-            adapter!!.addListener(this)
+        if (adapter == null) {
+            adapter = FlexibleAdapter(userItems, this, true)
         }
+
+        val layoutManager = SmoothScrollLinearLayoutManager(this)
+        binding.recyclerView.layoutManager = layoutManager
+        binding.recyclerView.setHasFixedSize(true)
+        binding.recyclerView.adapter = adapter
+        binding.recyclerView.isNestedScrollingEnabled = false
+        adapter!!.addListener(this)
     }
 
     private fun handleParticipants(participants: List<Participant>) {
@@ -435,7 +440,7 @@ class ConversationInfoController(args: Bundle) :
 
         for (i in participants.indices) {
             participant = participants[i]
-            userItem = ParticipantItem(router.activity, participant, conversationUser, viewThemeUtils)
+            userItem = ParticipantItem(this, participant, conversationUser, viewThemeUtils)
             if (participant.sessionId != null) {
                 userItem.isOnline = !participant.sessionId.equals("0")
             } else {
@@ -461,18 +466,10 @@ class ConversationInfoController(args: Bundle) :
 
         setupAdapter()
 
-        binding?.participantsListCategory?.visibility = VISIBLE
+        binding.participantsListCategory?.visibility = VISIBLE
         adapter!!.updateDataSet(userItems)
     }
 
-    override val title: String
-        get() =
-            if (hasAvatarSpacing) {
-                " " + resources!!.getString(R.string.nc_conversation_menu_conversation_info)
-            } else {
-                resources!!.getString(R.string.nc_conversation_menu_conversation_info)
-            }
-
     private fun getListOfParticipants() {
         var apiVersion = 1
         // FIXME Fix API checking with guests?
@@ -528,19 +525,9 @@ class ConversationInfoController(args: Bundle) :
         bundle.putStringArrayList(BundleKeys.KEY_EXISTING_PARTICIPANTS, existingParticipantsId)
         bundle.putString(BundleKeys.KEY_TOKEN, conversation!!.token)
 
-        router.pushController(
-            (
-                RouterTransaction.with(
-                    ContactsController(bundle)
-                )
-                    .pushChangeHandler(
-                        HorizontalChangeHandler()
-                    )
-                    .popChangeHandler(
-                        HorizontalChangeHandler()
-                    )
-                )
-        )
+        val intent = Intent(this, ContactsActivity::class.java)
+        intent.putExtras(bundle)
+        startActivity(intent)
     }
 
     private fun leaveConversation() {
@@ -551,37 +538,38 @@ class ConversationInfoController(args: Bundle) :
                         .java
                 ).setInputData(it).build()
             )
-            router.popToRoot()
+
+            val intent = Intent(context, MainActivity::class.java)
+            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+            startActivity(intent)
         }
     }
 
     private fun showClearHistoryDialog() {
-        if (activity != null) {
-            binding?.conversationInfoName?.context?.let {
-                val dialogBuilder = MaterialAlertDialogBuilder(it)
-                    .setIcon(
-                        viewThemeUtils.dialog.colorMaterialAlertDialogIcon(
-                            context,
-                            R.drawable.ic_delete_black_24dp
-                        )
+        binding.conversationInfoName.context.let {
+            val dialogBuilder = MaterialAlertDialogBuilder(it)
+                .setIcon(
+                    viewThemeUtils.dialog.colorMaterialAlertDialogIcon(
+                        context,
+                        R.drawable.ic_delete_black_24dp
                     )
-                    .setTitle(R.string.nc_clear_history)
-                    .setMessage(R.string.nc_clear_history_warning)
-                    .setPositiveButton(R.string.nc_delete_all) { _, _ ->
-                        clearHistory()
-                    }
-                    .setNegativeButton(R.string.nc_cancel) { _, _ ->
-                        // unused atm
-                    }
-
-                viewThemeUtils.dialog
-                    .colorMaterialAlertDialogBackground(it, dialogBuilder)
-                val dialog = dialogBuilder.show()
-                viewThemeUtils.platform.colorTextButtons(
-                    dialog.getButton(AlertDialog.BUTTON_POSITIVE),
-                    dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
                 )
-            }
+                .setTitle(R.string.nc_clear_history)
+                .setMessage(R.string.nc_clear_history_warning)
+                .setPositiveButton(R.string.nc_delete_all) { _, _ ->
+                    clearHistory()
+                }
+                .setNegativeButton(R.string.nc_cancel) { _, _ ->
+                    // unused atm
+                }
+
+            viewThemeUtils.dialog
+                .colorMaterialAlertDialogBackground(it, dialogBuilder)
+            val dialog = dialogBuilder.show()
+            viewThemeUtils.platform.colorTextButtons(
+                dialog.getButton(AlertDialog.BUTTON_POSITIVE),
+                dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
+            )
         }
     }
 
@@ -590,7 +578,7 @@ class ConversationInfoController(args: Bundle) :
 
         ncApi.clearChatHistory(
             credentials,
-            ApiUtils.getUrlForChat(apiVersion, conversationUser!!.baseUrl, conversationToken)
+            ApiUtils.getUrlForChat(apiVersion, conversationUser.baseUrl, conversationToken)
         )
             ?.subscribeOn(Schedulers.io())
             ?.observeOn(AndroidSchedulers.mainThread())
@@ -622,7 +610,9 @@ class ConversationInfoController(args: Bundle) :
                     DeleteConversationWorker::class.java
                 ).setInputData(it).build()
             )
-            router.popToRoot()
+            val intent = Intent(context, MainActivity::class.java)
+            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+            startActivity(intent)
         }
     }
 
@@ -659,7 +649,7 @@ class ConversationInfoController(args: Bundle) :
                         binding?.clearConversationHistory?.visibility = GONE
                     }
 
-                    if (isAttached && (!isBeingDestroyed || !isDestroyed)) {
+                    if (!isDestroyed) {
                         binding?.ownOptions?.visibility = VISIBLE
 
                         setupWebinaryView()
@@ -706,7 +696,7 @@ class ConversationInfoController(args: Bundle) :
 
                         binding?.let {
                             GuestAccessHelper(
-                                this@ConversationInfoController,
+                                this@ConversationInfoActivity,
                                 it,
                                 conversation!!,
                                 conversationUser
@@ -882,7 +872,7 @@ class ConversationInfoController(args: Bundle) :
                 credentials,
                 ApiUtils.getUrlForRoomModerators(
                     apiVersion,
-                    conversationUser!!.baseUrl,
+                    conversationUser.baseUrl,
                     conversation!!.token
                 ),
                 participant.userId
@@ -895,7 +885,7 @@ class ConversationInfoController(args: Bundle) :
                 credentials,
                 ApiUtils.getUrlForRoomModerators(
                     apiVersion,
-                    conversationUser!!.baseUrl,
+                    conversationUser.baseUrl,
                     conversation!!.token
                 ),
                 participant.userId
@@ -912,7 +902,7 @@ class ConversationInfoController(args: Bundle) :
                 credentials,
                 ApiUtils.getUrlForAttendees(
                     apiVersion,
-                    conversationUser!!.baseUrl,
+                    conversationUser.baseUrl,
                     conversation!!.token
                 ),
                 participant.attendeeId
@@ -944,7 +934,7 @@ class ConversationInfoController(args: Bundle) :
                 ncApi.removeParticipantFromConversation(
                     credentials,
                     ApiUtils.getUrlForRemovingParticipantFromConversation(
-                        conversationUser!!.baseUrl,
+                        conversationUser.baseUrl,
                         conversation!!.token,
                         true
                     ),
@@ -974,7 +964,7 @@ class ConversationInfoController(args: Bundle) :
                 ncApi.removeParticipantFromConversation(
                     credentials,
                     ApiUtils.getUrlForRemovingParticipantFromConversation(
-                        conversationUser!!.baseUrl,
+                        conversationUser.baseUrl,
                         conversation!!.token,
                         false
                     ),
@@ -1005,7 +995,7 @@ class ConversationInfoController(args: Bundle) :
     }
 
     override fun onItemClick(view: View?, position: Int): Boolean {
-        if (!conversation!!.canModerate(conversationUser!!)) {
+        if (!conversation!!.canModerate(conversationUser)) {
             return true
         }
 
@@ -1022,7 +1012,7 @@ class ConversationInfoController(args: Bundle) :
                         context.getString(R.string.nc_attendee_pin, participant.attendeePin)
                     )
                 )
-                MaterialDialog(activity!!, BottomSheet(WRAP_CONTENT)).show {
+                MaterialDialog(this, BottomSheet(WRAP_CONTENT)).show {
                     cornerRadius(res = R.dimen.corner_radius)
 
                     title(text = participant.displayName)
@@ -1048,7 +1038,7 @@ class ConversationInfoController(args: Bundle) :
                     context.getString(R.string.nc_remove_group_and_members)
                 )
             )
-            MaterialDialog(activity!!, BottomSheet(WRAP_CONTENT)).show {
+            MaterialDialog(this, BottomSheet(WRAP_CONTENT)).show {
                 cornerRadius(res = R.dimen.corner_radius)
 
                 title(text = participant.displayName)
@@ -1068,7 +1058,7 @@ class ConversationInfoController(args: Bundle) :
                     context.getString(R.string.nc_remove_circle_and_members)
                 )
             )
-            MaterialDialog(activity!!, BottomSheet(WRAP_CONTENT)).show {
+            MaterialDialog(this, BottomSheet(WRAP_CONTENT)).show {
                 cornerRadius(res = R.dimen.corner_radius)
 
                 title(text = participant.displayName)
@@ -1119,7 +1109,7 @@ class ConversationInfoController(args: Bundle) :
         }
 
         if (items.isNotEmpty()) {
-            MaterialDialog(activity!!, BottomSheet(WRAP_CONTENT)).show {
+            MaterialDialog(this, BottomSheet(WRAP_CONTENT)).show {
                 cornerRadius(res = R.dimen.corner_radius)
 
                 title(text = participant.displayName)

+ 4 - 6
app/src/main/java/com/nextcloud/talk/conversation/info/GuestAccessHelper.kt

@@ -10,7 +10,6 @@ import androidx.appcompat.app.AlertDialog
 import androidx.appcompat.widget.SwitchCompat
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
 import com.nextcloud.talk.R
-import com.nextcloud.talk.controllers.ConversationInfoController
 import com.nextcloud.talk.data.user.model.User
 import com.nextcloud.talk.databinding.ControllerConversationInfoBinding
 import com.nextcloud.talk.databinding.DialogPasswordBinding
@@ -24,16 +23,15 @@ import io.reactivex.disposables.Disposable
 import io.reactivex.schedulers.Schedulers
 
 class GuestAccessHelper(
-    controller: ConversationInfoController,
+    private val activity: ConversationInfoActivity,
     private val binding: ControllerConversationInfoBinding,
     private val conversation: Conversation,
     private val conversationUser: User
 ) {
 
-    private val activity = controller.activity!!
-    private val conversationsRepository = controller.conversationsRepository
-    private val viewThemeUtils = controller.viewThemeUtils
-    private val context = controller.context
+    private val conversationsRepository = activity.conversationsRepository
+    private val viewThemeUtils = activity.viewThemeUtils
+    private val context = activity.context
 
     fun setupGuestAccess() {
         val guestAccessAllowSwitch = (

+ 1 - 0
app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.kt

@@ -86,4 +86,5 @@ object BundleKeys {
     const val KEY_DISMISS_RECORDING_URL = "KEY_DISMISS_RECORDING_URL"
     const val KEY_SHARE_RECORDING_TO_CHAT_URL = "KEY_SHARE_RECORDING_TO_CHAT_URL"
     const val KEY_GEOCODING_RESULT = "KEY_GEOCODING_RESULT"
+    const val KEY_OPEN_CHAT = "KEY_OPEN_CHAT" // just temporarily used until conductor is deleted
 }

+ 18 - 0
app/src/main/res/layout/controller_contacts_rv.xml

@@ -19,11 +19,29 @@
   -->
 <LinearLayout 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="match_parent"
     android:orientation="vertical"
     android:animateLayoutChanges="true">
 
+    <com.google.android.material.appbar.AppBarLayout
+        android:id="@+id/contacts_appbar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <com.google.android.material.appbar.MaterialToolbar
+            android:id="@+id/contacts_toolbar"
+            android:layout_width="match_parent"
+            android:layout_height="?attr/actionBarSize"
+            android:background="@color/appbar"
+            android:theme="?attr/actionBarPopupTheme"
+            app:layout_scrollFlags="scroll|enterAlways"
+            app:navigationIconTint="@color/fontAppbar"
+            app:popupTheme="@style/appActionBarPopupMenu"
+            app:titleTextColor="@color/fontAppbar"
+            tools:title="@string/nc_app_product_name" />
+    </com.google.android.material.appbar.AppBarLayout>
+
     <LinearLayout
         android:id="@+id/loading_content"
         android:layout_width="match_parent"

+ 23 - 5
app/src/main/res/layout/controller_conversation_info.xml

@@ -6,7 +6,7 @@
   ~ @author Marcel Hibbe
   ~ @author Tim Krüger
   ~ Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
-  ~ Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
+  ~ Copyright (C) 2022-2023 Marcel Hibbe <dev@mhibbe.de>
   ~ Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
   ~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
   ~
@@ -24,13 +24,31 @@
   ~ along with this program.  If not, see <http://www.gnu.org/licenses/>.
   -->
 
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:apc="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/parent_container"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical"
-    tools:background="@color/white">
+    android:orientation="vertical">
+
+    <com.google.android.material.appbar.AppBarLayout
+        android:id="@+id/conversation_info_appbar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <com.google.android.material.appbar.MaterialToolbar
+            android:id="@+id/conversation_info_toolbar"
+            android:layout_width="match_parent"
+            android:layout_height="?attr/actionBarSize"
+            android:background="@color/appbar"
+            android:theme="?attr/actionBarPopupTheme"
+            app:layout_scrollFlags="scroll|enterAlways"
+            app:navigationIconTint="@color/fontAppbar"
+            app:popupTheme="@style/appActionBarPopupMenu"
+            app:titleTextColor="@color/fontAppbar"
+            tools:title="@string/nc_app_product_name" />
+    </com.google.android.material.appbar.AppBarLayout>
 
     <ProgressBar
         android:id="@+id/progressBar"
@@ -279,4 +297,4 @@
 
         </LinearLayout>
     </ScrollView>
-</RelativeLayout>
+</LinearLayout>