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

Replace Controller with Activity for conversationInfo and contacts
This commit is contained in:
Marcel Hibbe 2023-03-31 12:59:43 +02:00 committed by GitHub
commit c5d97175d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 422 additions and 356 deletions

View File

@ -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>

View File

@ -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()) {

View File

@ -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,41 +750,33 @@ 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
)
contactsBottomDialog?.dismiss()
}
// ConductorRemapping.remapChatController(
// router,
// currentUser!!.id!!,
// openConversationEvent.conversation!!.token!!,
// openConversationEvent.bundle!!,
// true
// )
override fun onDetach(view: View) {
super.onDetach(view)
eventBus.unregister(this)
// 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 onItemClick(view: View, position: Int): Boolean {
@ -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) {

View File

@ -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() {

View File

@ -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?) {

View File

@ -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)
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 onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
router.popCurrentController()
return true
}
else -> return super.onOptionsItemSelected(item)
}
}
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)

View File

@ -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 = (

View File

@ -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
}

View File

@ -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"

View File

@ -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>