diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c15528198..f0a8abb22 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -224,6 +224,10 @@ android:launchMode="singleInstance" android:screenOrientation="portrait" /> + + diff --git a/app/src/main/java/com/nextcloud/talk/activities/BaseActivity.kt b/app/src/main/java/com/nextcloud/talk/activities/BaseActivity.kt index 890feaff2..74ff337c3 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/BaseActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/activities/BaseActivity.kt @@ -48,6 +48,10 @@ import javax.inject.Inject @AutoInjector(NextcloudTalkApplication::class) open class BaseActivity : AppCompatActivity() { + enum class AppBarLayoutType { + TOOLBAR, SEARCH_BAR, EMPTY + } + @Inject lateinit var eventBus: EventBus @@ -60,6 +64,9 @@ open class BaseActivity : AppCompatActivity() { @Inject lateinit var context: Context + open val appBarLayoutType: AppBarLayoutType + get() = AppBarLayoutType.TOOLBAR + override fun onCreate(savedInstanceState: Bundle?) { NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this) super.onCreate(savedInstanceState) diff --git a/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt b/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt index ec29dfeab..52ad728b4 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt @@ -40,15 +40,14 @@ import com.nextcloud.talk.R import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.chat.ChatActivity -import com.nextcloud.talk.controllers.ConversationsListController import com.nextcloud.talk.controllers.LockedController import com.nextcloud.talk.controllers.ServerSelectionController import com.nextcloud.talk.controllers.WebViewLoginController import com.nextcloud.talk.controllers.base.providers.ActionBarProvider +import com.nextcloud.talk.conversationlist.ConversationsListActivity import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.databinding.ActivityMainBinding import com.nextcloud.talk.models.json.conversations.RoomOverall -import com.nextcloud.talk.settings.SettingsActivity import com.nextcloud.talk.users.UserManager import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.SecurityUtils @@ -165,11 +164,10 @@ class MainActivity : BaseActivity(), ActionBarProvider { } private fun setDefaultRootController() { - router!!.setRoot( - RouterTransaction.with(ConversationsListController(Bundle())) - .pushChangeHandler(HorizontalChangeHandler()) - .popChangeHandler(HorizontalChangeHandler()) - ) + val intent = Intent(this, ConversationsListActivity::class.java) + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) + intent.putExtras(Bundle()) + startActivity(intent) } fun resetConversationsList() { @@ -192,11 +190,6 @@ class MainActivity : BaseActivity(), ActionBarProvider { }) } - fun openSettings() { - val intent = Intent(this, SettingsActivity::class.java) - startActivity(intent) - } - fun addAccount() { router!!.pushController( RouterTransaction.with(ServerSelectionController()) diff --git a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt index 83cb5ad5b..40fc80d71 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt @@ -121,8 +121,8 @@ import com.nextcloud.talk.adapters.messages.VoiceMessageInterface import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.callbacks.MentionAutocompleteCallback -import com.nextcloud.talk.controllers.ConversationsListController import com.nextcloud.talk.conversation.info.ConversationInfoActivity +import com.nextcloud.talk.conversationlist.ConversationsListActivity import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.databinding.ControllerChatBinding import com.nextcloud.talk.events.UserMentionClickEvent @@ -1763,7 +1763,7 @@ class ChatActivity : super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == UploadAndShareFilesWorker.REQUEST_PERMISSION) { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - Log.d(ConversationsListController.TAG, "upload starting after permissions were granted") + Log.d(ConversationsListActivity.TAG, "upload starting after permissions were granted") if (filesToUpload.isNotEmpty()) { uploadFiles(filesToUpload) } @@ -3154,12 +3154,9 @@ class ChatActivity : bundle.putString(BundleKeys.KEY_FORWARD_MSG_TEXT, message?.text) bundle.putString(BundleKeys.KEY_FORWARD_HIDE_SOURCE_ROOM, roomId) - // TODO - // router.pushController( - // RouterTransaction.with(ConversationsListController(bundle)) - // .pushChangeHandler(HorizontalChangeHandler()) - // .popChangeHandler(HorizontalChangeHandler()) - // ) + val intent = Intent(this, ConversationsListActivity::class.java) + intent.putExtras(bundle) + startActivity(intent) } fun markAsUnread(message: IMessage?) { diff --git a/app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.kt b/app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.kt index f275b6fba..dff638289 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.kt @@ -22,6 +22,7 @@ package com.nextcloud.talk.controllers import android.annotation.SuppressLint +import android.content.Intent import android.content.pm.ActivityInfo import android.os.Bundle import android.os.Handler @@ -42,6 +43,7 @@ import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication import com.nextcloud.talk.controllers.base.BaseController import com.nextcloud.talk.controllers.util.viewBinding +import com.nextcloud.talk.conversationlist.ConversationsListActivity import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.databinding.ControllerAccountVerificationBinding import com.nextcloud.talk.events.EventStatus @@ -457,11 +459,8 @@ class AccountVerificationController(args: Bundle? = null) : if (activity != null) { activity!!.runOnUiThread { if (userManager.users.blockingGet().size == 1) { - router.setRoot( - RouterTransaction.with(ConversationsListController(Bundle())) - .pushChangeHandler(HorizontalChangeHandler()) - .popChangeHandler(HorizontalChangeHandler()) - ) + val intent = Intent(context, ConversationsListActivity::class.java) + startActivity(intent) } else { if (isAccountImport) { ApplicationWideMessageHolder.getInstance().messageType = @@ -517,11 +516,8 @@ class AccountVerificationController(args: Bundle? = null) : } } else { if (userManager.users.blockingGet().isNotEmpty()) { - router.setRoot( - RouterTransaction.with(ConversationsListController(Bundle())) - .pushChangeHandler(HorizontalChangeHandler()) - .popChangeHandler(HorizontalChangeHandler()) - ) + val intent = Intent(context, ConversationsListActivity::class.java) + startActivity(intent) } else { router.setRoot( RouterTransaction.with(ServerSelectionController()) diff --git a/app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.kt b/app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.kt index 1eb5657c6..a6ec70ade 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.kt @@ -22,10 +22,7 @@ */ package com.nextcloud.talk.controllers.base -import android.animation.AnimatorInflater -import android.app.Activity import android.content.Context -import android.content.res.Resources import android.os.Build import android.os.Bundle import android.util.Log @@ -39,12 +36,10 @@ import android.widget.EditText import androidx.annotation.LayoutRes import androidx.annotation.RequiresApi import androidx.appcompat.app.ActionBar -import androidx.core.content.res.ResourcesCompat import autodagger.AutoInjector import com.bluelinelabs.conductor.Controller import com.bluelinelabs.conductor.ControllerChangeHandler import com.bluelinelabs.conductor.ControllerChangeType -import com.google.android.material.appbar.AppBarLayout import com.nextcloud.talk.R import com.nextcloud.talk.activities.MainActivity import com.nextcloud.talk.application.NextcloudTalkApplication @@ -54,9 +49,7 @@ import com.nextcloud.talk.controllers.ServerSelectionController import com.nextcloud.talk.controllers.SwitchAccountController import com.nextcloud.talk.controllers.WebViewLoginController import com.nextcloud.talk.controllers.base.providers.ActionBarProvider -import com.nextcloud.talk.databinding.ActivityMainBinding import com.nextcloud.talk.ui.theme.ViewThemeUtils -import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.preferences.AppPreferences import javax.inject.Inject import kotlin.jvm.internal.Intrinsics @@ -120,12 +113,12 @@ abstract class BaseController(@LayoutRes var layoutRes: Int, args: Bundle? = nul protected open fun onViewBound(view: View) { var activity: MainActivity? = null - if (getActivity() != null && getActivity() is MainActivity) { - activity = getActivity() as MainActivity? - viewThemeUtils.material.themeCardView(activity!!.binding.searchToolbar) - viewThemeUtils.material.themeToolbar(activity.binding.toolbar) - viewThemeUtils.material.themeSearchBarText(activity.binding.searchText) - } + // if (getActivity() != null && getActivity() is MainActivity) { + // activity = getActivity() as MainActivity? + // viewThemeUtils.material.themeCardView(activity!!.binding.searchToolbar) + // viewThemeUtils.material.themeToolbar(activity.binding.toolbar) + // viewThemeUtils.material.themeSearchBarText(activity.binding.searchText) + // } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && appPreferences.isKeyboardIncognito) { disableKeyboardPersonalisedLearning((view as ViewGroup)) @@ -136,7 +129,7 @@ abstract class BaseController(@LayoutRes var layoutRes: Int, args: Bundle? = nul } override fun onAttach(view: View) { - showSearchOrToolbar() + // showSearchOrToolbar() setTitle() if (actionBar != null) { actionBar!!.setDisplayHomeAsUpEnabled(parentController != null || router.backstackSize >= 1) @@ -144,93 +137,93 @@ abstract class BaseController(@LayoutRes var layoutRes: Int, args: Bundle? = nul super.onAttach(view) } - open fun showSearchOrToolbar() { - if (isValidActivity(activity)) { - val showSearchBar = appBarLayoutType == AppBarLayoutType.SEARCH_BAR - val activity = activity as MainActivity - - if (appBarLayoutType == AppBarLayoutType.EMPTY) { - hideBars(activity.binding) - } else { - if (showSearchBar) { - showSearchBar(activity.binding) - } else { - showToolbar(activity.binding) - } - colorizeStatusBar(showSearchBar, activity, resources) - } - - colorizeNavigationBar(activity, resources) - } - } - - private fun isValidActivity(activity: Activity?): Boolean { - return activity != null && activity is MainActivity - } - - private fun showSearchBar(binding: ActivityMainBinding) { - val layoutParams = binding.searchToolbar.layoutParams as AppBarLayout.LayoutParams - binding.searchToolbar.visibility = View.VISIBLE - binding.searchText.hint = searchHint - binding.toolbar.visibility = View.GONE - // layoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout - // .LayoutParams.SCROLL_FLAG_SNAP | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); - layoutParams.scrollFlags = 0 - binding.appBar.stateListAnimator = AnimatorInflater.loadStateListAnimator( - binding.appBar.context, - R.animator.appbar_elevation_off - ) - binding.searchToolbar.layoutParams = layoutParams - } - - private fun showToolbar(binding: ActivityMainBinding) { - val layoutParams = binding.searchToolbar.layoutParams as AppBarLayout.LayoutParams - binding.searchToolbar.visibility = View.GONE - binding.toolbar.visibility = View.VISIBLE - viewThemeUtils.material.colorToolbarOverflowIcon(binding.toolbar) - layoutParams.scrollFlags = 0 - binding.appBar.stateListAnimator = AnimatorInflater.loadStateListAnimator( - binding.appBar.context, - R.animator.appbar_elevation_on - ) - binding.searchToolbar.layoutParams = layoutParams - } - - private fun hideBars(binding: ActivityMainBinding) { - binding.toolbar.visibility = View.GONE - binding.searchToolbar.visibility = View.GONE - } - - fun hideSearchBar() { - val activity = activity as MainActivity? - val layoutParams = activity!!.binding.searchToolbar.layoutParams as AppBarLayout.LayoutParams - activity.binding.searchToolbar.visibility = View.GONE - activity.binding.toolbar.visibility = View.VISIBLE - layoutParams.scrollFlags = 0 - activity.binding.appBar.stateListAnimator = AnimatorInflater.loadStateListAnimator( - activity.binding.appBar.context, - R.animator.appbar_elevation_on - ) - } - - private fun colorizeStatusBar(showSearchBar: Boolean, activity: Activity?, resources: Resources?) { - if (activity != null && resources != null) { - if (showSearchBar) { - view?.let { viewThemeUtils.platform.resetStatusBar(activity) } - } else { - view?.let { viewThemeUtils.platform.themeStatusBar(activity, it) } - } - } - } - - private fun colorizeNavigationBar(activity: Activity?, resources: Resources?) { - if (activity != null && resources != null) { - DisplayUtils.applyColorToNavigationBar( - activity.window, - ResourcesCompat.getColor(resources, R.color.bg_default, null) - ) - } - } + // open fun showSearchOrToolbar() { + // if (isValidActivity(activity)) { + // val showSearchBar = appBarLayoutType == AppBarLayoutType.SEARCH_BAR + // val activity = activity as MainActivity + // + // if (appBarLayoutType == AppBarLayoutType.EMPTY) { + // hideBars(activity.binding) + // } else { + // if (showSearchBar) { + // showSearchBar(activity.binding) + // } else { + // showToolbar(activity.binding) + // } + // colorizeStatusBar(showSearchBar, activity, resources) + // } + // + // colorizeNavigationBar(activity, resources) + // } + // } + // + // private fun isValidActivity(activity: Activity?): Boolean { + // return activity != null && activity is MainActivity + // } + // + // private fun showSearchBar(binding: ActivityMainBinding) { + // val layoutParams = binding.searchToolbar.layoutParams as AppBarLayout.LayoutParams + // binding.searchToolbar.visibility = View.VISIBLE + // binding.searchText.hint = searchHint + // binding.toolbar.visibility = View.GONE + // // layoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout + // // .LayoutParams.SCROLL_FLAG_SNAP | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); + // layoutParams.scrollFlags = 0 + // binding.appBar.stateListAnimator = AnimatorInflater.loadStateListAnimator( + // binding.appBar.context, + // R.animator.appbar_elevation_off + // ) + // binding.searchToolbar.layoutParams = layoutParams + // } + // + // private fun showToolbar(binding: ActivityMainBinding) { + // val layoutParams = binding.searchToolbar.layoutParams as AppBarLayout.LayoutParams + // binding.searchToolbar.visibility = View.GONE + // binding.toolbar.visibility = View.VISIBLE + // viewThemeUtils.material.colorToolbarOverflowIcon(binding.toolbar) + // layoutParams.scrollFlags = 0 + // binding.appBar.stateListAnimator = AnimatorInflater.loadStateListAnimator( + // binding.appBar.context, + // R.animator.appbar_elevation_on + // ) + // binding.searchToolbar.layoutParams = layoutParams + // } + // + // private fun hideBars(binding: ActivityMainBinding) { + // binding.toolbar.visibility = View.GONE + // binding.searchToolbar.visibility = View.GONE + // } + // + // fun hideSearchBar() { + // val activity = activity as MainActivity? + // val layoutParams = activity!!.binding.searchToolbar.layoutParams as AppBarLayout.LayoutParams + // activity.binding.searchToolbar.visibility = View.GONE + // activity.binding.toolbar.visibility = View.VISIBLE + // layoutParams.scrollFlags = 0 + // activity.binding.appBar.stateListAnimator = AnimatorInflater.loadStateListAnimator( + // activity.binding.appBar.context, + // R.animator.appbar_elevation_on + // ) + // } + // + // private fun colorizeStatusBar(showSearchBar: Boolean, activity: Activity?, resources: Resources?) { + // if (activity != null && resources != null) { + // if (showSearchBar) { + // view?.let { viewThemeUtils.platform.resetStatusBar(activity) } + // } else { + // view?.let { viewThemeUtils.platform.themeStatusBar(activity, it) } + // } + // } + // } + // + // private fun colorizeNavigationBar(activity: Activity?, resources: Resources?) { + // if (activity != null && resources != null) { + // DisplayUtils.applyColorToNavigationBar( + // activity.window, + // ResourcesCompat.getColor(resources, R.color.bg_default, null) + // ) + // } + // } override fun onDetach(view: View) { super.onDetach(view) diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt b/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt similarity index 75% rename from app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt rename to app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt index 6e8c6d3ab..d19df209f 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt +++ b/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt @@ -23,14 +23,17 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.nextcloud.talk.controllers +package com.nextcloud.talk.conversationlist import android.animation.AnimatorInflater import android.annotation.SuppressLint +import android.app.Activity import android.app.SearchManager import android.content.Context import android.content.Intent import android.content.pm.PackageManager +import android.content.res.Resources +import android.graphics.drawable.ColorDrawable import android.graphics.drawable.Drawable import android.net.Uri import android.os.Build @@ -40,7 +43,6 @@ import android.text.InputType import android.text.TextUtils import android.util.Log import android.view.Menu -import android.view.MenuInflater import android.view.MenuItem import android.view.MotionEvent import android.view.View @@ -49,6 +51,7 @@ import android.view.inputmethod.InputMethodManager import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.appcompat.widget.SearchView +import androidx.core.content.res.ResourcesCompat import androidx.core.view.MenuItemCompat import androidx.fragment.app.DialogFragment import androidx.recyclerview.widget.RecyclerView @@ -60,13 +63,12 @@ import coil.imageLoader import coil.request.ImageRequest import coil.target.Target import coil.transform.CircleCropTransformation -import com.bluelinelabs.conductor.RouterTransaction -import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler +import com.google.android.material.appbar.AppBarLayout import com.google.android.material.button.MaterialButton import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.nextcloud.talk.R +import com.nextcloud.talk.activities.BaseActivity import com.nextcloud.talk.activities.CallActivity -import com.nextcloud.talk.activities.MainActivity import com.nextcloud.talk.adapters.items.ConversationItem import com.nextcloud.talk.adapters.items.GenericTextHeaderItem import com.nextcloud.talk.adapters.items.LoadMoreResultsItem @@ -74,11 +76,8 @@ import com.nextcloud.talk.adapters.items.MessageResultItem 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.chat.ChatActivity 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 import com.nextcloud.talk.databinding.ControllerConversationsRvBinding import com.nextcloud.talk.events.ConversationsListFetchDataEvent @@ -100,6 +99,7 @@ import com.nextcloud.talk.ui.dialog.ConversationsListBottomDialog import com.nextcloud.talk.users.UserManager import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ClosedInterfaceImpl +import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.FileUtils import com.nextcloud.talk.utils.Mimetype import com.nextcloud.talk.utils.ParticipantPermissions @@ -130,7 +130,6 @@ import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable import io.reactivex.schedulers.Schedulers import org.apache.commons.lang3.builder.CompareToBuilder -import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode import org.parceler.Parcels @@ -140,19 +139,17 @@ import java.util.concurrent.TimeUnit import javax.inject.Inject @AutoInjector(NextcloudTalkApplication::class) -class ConversationsListController(bundle: Bundle) : - BaseController(R.layout.controller_conversations_rv, bundle), +class ConversationsListActivity : + BaseActivity(), FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemLongClickListener, ConversationMenuInterface { - private val bundle: Bundle + + private lateinit var binding: ControllerConversationsRvBinding @Inject lateinit var userManager: UserManager - @Inject - lateinit var eventBus: EventBus - @Inject lateinit var ncApi: NcApi @@ -162,11 +159,6 @@ class ConversationsListController(bundle: Bundle) : @Inject lateinit var platformPermissionUtil: PlatformPermissionUtil - private val binding: ControllerConversationsRvBinding? by viewBinding(ControllerConversationsRvBinding::bind) - - override val title: String - get() = resources!!.getString(R.string.nc_app_product_name) - override val appBarLayoutType: AppBarLayoutType get() = AppBarLayoutType.SEARCH_BAR @@ -190,7 +182,7 @@ class ConversationsListController(bundle: Bundle) : private var selectedConversation: Conversation? = null private var textToPaste: String? = "" private var selectedMessageId: String? = null - private var forwardMessage: Boolean + private var forwardMessage: Boolean = false private var nextUnreadConversationScrollPosition = 0 private var layoutManager: SmoothScrollLinearLayoutManager? = null private val callHeaderItems = HashMap() @@ -198,46 +190,110 @@ class ConversationsListController(bundle: Bundle) : private var searchHelper: MessageSearchHelper? = null private var searchViewDisposable: Disposable? = null - override fun onViewBound(view: View) { - super.onViewBound(view) - sharedApplication!!.componentApplication.inject(this) - actionBar?.show() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this) + + binding = ControllerConversationsRvBinding.inflate(layoutInflater) + setupActionBar() + setupSystemColors() + setContentView(binding.root) + + forwardMessage = intent.getBooleanExtra(KEY_FORWARD_MSG_FLAG, false) + } + + override fun onResume() { + super.onResume() + + // actionBar?.show() if (adapter == null) { - adapter = FlexibleAdapter(conversationItems, activity, true) + adapter = FlexibleAdapter(conversationItems, this, true) } else { binding?.loadingContent?.visibility = View.GONE } adapter!!.addListener(this) prepareViews() + + showShareToScreen = hasActivityActionSendIntent() + + ClosedInterfaceImpl().setUpPushTokenRegistration() + if (!eventBus.isRegistered(this)) { + eventBus.register(this) + } + currentUser = userManager.currentUser.blockingGet() + if (currentUser != null) { + if (isServerEOL(currentUser!!)) { + showServerEOLDialog() + return + } + if (isUnifiedSearchAvailable(currentUser!!)) { + searchHelper = MessageSearchHelper(unifiedSearchRepository) + } + credentials = ApiUtils.getCredentials(currentUser!!.username, currentUser!!.token) + + loadUserAvatar(binding.switchAccountButton) + viewThemeUtils.material.colorMaterialTextButton(binding.switchAccountButton) + + fetchRooms() + } else { + Log.e(TAG, "userManager.currentUser.blockingGet() returned null") + Toast.makeText(context, R.string.nc_common_error_sorry, Toast.LENGTH_LONG).show() + } + + showSearchOrToolbar() + } + + private fun setupActionBar() { + setSupportActionBar(binding.conversationListToolbar) + binding.conversationListToolbar.setNavigationOnClickListener { + onBackPressed() + } + supportActionBar?.setDisplayHomeAsUpEnabled(true) + supportActionBar?.setDisplayShowHomeEnabled(true) + supportActionBar?.setIcon(ColorDrawable(resources!!.getColor(R.color.transparent))) + supportActionBar?.title = 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) + ) } private fun loadUserAvatar( target: Target ) { - if (activity != null) { - if (currentUser != null) { - val url = ApiUtils.getUrlForAvatar( - currentUser!!.baseUrl, - currentUser!!.userId, - true - ) + if (currentUser != null) { + val url = ApiUtils.getUrlForAvatar( + currentUser!!.baseUrl, + currentUser!!.userId, + true + ) - val credentials = ApiUtils.getCredentials(currentUser!!.username, currentUser!!.token) + val credentials = ApiUtils.getCredentials(currentUser!!.username, currentUser!!.token) - context.imageLoader.enqueue( - ImageRequest.Builder(context) - .data(url) - .addHeader("Authorization", credentials) - .placeholder(R.drawable.ic_user) - .transformations(CircleCropTransformation()) - .crossfade(true) - .target(target) - .build() - ) - } else { - Log.e(TAG, "currentUser was null in loadUserAvatar") - Toast.makeText(context, R.string.nc_common_error_sorry, Toast.LENGTH_LONG).show() - } + context.imageLoader.enqueue( + ImageRequest.Builder(context) + .data(url) + .addHeader("Authorization", credentials) + .placeholder(R.drawable.ic_user) + .transformations(CircleCropTransformation()) + .crossfade(true) + .target(target) + .build() + ) + } else { + Log.e(TAG, "currentUser was null in loadUserAvatar") + Toast.makeText(context, R.string.nc_common_error_sorry, Toast.LENGTH_LONG).show() } } @@ -268,92 +324,44 @@ class ConversationsListController(bundle: Bundle) : loadUserAvatar(target) } - override fun onAttach(view: View) { - Log.d( - TAG, - "onAttach: Controller: " + System.identityHashCode(this) + - " Activity: " + System.identityHashCode(activity) - ) - super.onAttach(view) - - showShareToScreen = hasActivityActionSendIntent() - - ClosedInterfaceImpl().setUpPushTokenRegistration() - if (!eventBus.isRegistered(this)) { - eventBus.register(this) - } - currentUser = userManager.currentUser.blockingGet() - if (currentUser != null) { - if (isServerEOL(currentUser!!)) { - showServerEOLDialog() - return - } - if (isUnifiedSearchAvailable(currentUser!!)) { - searchHelper = MessageSearchHelper(unifiedSearchRepository) - } - credentials = ApiUtils.getCredentials(currentUser!!.username, currentUser!!.token) - if (activity != null && activity is MainActivity) { - loadUserAvatar((activity as MainActivity?)!!.binding.switchAccountButton) - viewThemeUtils.material - .colorMaterialTextButton((activity as MainActivity?)!!.binding.switchAccountButton) - } - fetchRooms() - } else { - Log.e(TAG, "userManager.currentUser.blockingGet() returned null") - Toast.makeText(context, R.string.nc_common_error_sorry, Toast.LENGTH_LONG).show() - } - } - - override fun onDetach(view: View) { - Log.d( - TAG, - "onDetach: Controller: " + System.identityHashCode(this) + - " Activity: " + System.identityHashCode(activity) - ) - super.onDetach(view) - eventBus.unregister(this) - } - private fun initSearchView() { - if (activity != null) { - val 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 = EditorInfo.IME_ACTION_DONE or EditorInfo.IME_FLAG_NO_FULLSCREEN - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && appPreferences.isKeyboardIncognito) { - imeOptions = imeOptions or EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING - } - searchView!!.imeOptions = imeOptions - searchView!!.queryHint = searchHint - if (searchManager != null) { - searchView!!.setSearchableInfo(searchManager.getSearchableInfo(activity!!.componentName)) - } - searchViewDisposable = observeSearchView(searchView!!) - .debounce { query: String? -> - if (TextUtils.isEmpty(query)) { - return@debounce Observable.empty() - } else { - return@debounce Observable.timer( - SEARCH_DEBOUNCE_INTERVAL_MS.toLong(), - TimeUnit.MILLISECONDS - ) - } - } - .distinctUntilChanged() - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe { newText: String? -> onQueryTextChange(newText) } + val searchManager = 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 = EditorInfo.IME_ACTION_DONE or EditorInfo.IME_FLAG_NO_FULLSCREEN + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && appPreferences.isKeyboardIncognito) { + imeOptions = imeOptions or EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING } + searchView!!.imeOptions = imeOptions + searchView!!.queryHint = getString(R.string.appbar_search_in, getString(R.string.nc_app_product_name)) + if (searchManager != null) { + searchView!!.setSearchableInfo(searchManager.getSearchableInfo(componentName)) + } + searchViewDisposable = observeSearchView(searchView!!) + .debounce { query: String? -> + if (TextUtils.isEmpty(query)) { + return@debounce Observable.empty() + } else { + return@debounce Observable.timer( + SEARCH_DEBOUNCE_INTERVAL_MS.toLong(), + TimeUnit.MILLISECONDS + ) + } + } + .distinctUntilChanged() + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { newText: String? -> onQueryTextChange(newText) } } } - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - super.onCreateOptionsMenu(menu, inflater) + override fun onCreateOptionsMenu(menu: Menu): Boolean { + super.onCreateOptionsMenu(menu) - inflater.inflate(R.menu.menu_conversation_plus_filter, menu) + menuInflater.inflate(R.menu.menu_conversation_plus_filter, menu) searchItem = menu.findItem(R.id.action_search) chooseAccountItem = menu.findItem(R.id.action_choose_account) loadUserAvatar(chooseAccountItem!!) @@ -362,17 +370,19 @@ class ConversationsListController(bundle: Bundle) : if (resources != null && resources!!.getBoolean(R.bool.multiaccount_support)) { val newFragment: DialogFragment = ChooseAccountShareToDialogFragment.newInstance() newFragment.show( - (activity as MainActivity?)!!.supportFragmentManager, + supportFragmentManager, ChooseAccountShareToDialogFragment.TAG ) } true } initSearchView() + return true } - override fun onPrepareOptionsMenu(menu: Menu) { + override fun onPrepareOptionsMenu(menu: Menu): Boolean { super.onPrepareOptionsMenu(menu) + searchView = MenuItemCompat.getActionView(searchItem) as SearchView val moreAccountsAvailable = userManager.users.blockingGet().size > 1 @@ -385,24 +395,19 @@ class ConversationsListController(bundle: Bundle) : hideSearchBar() actionBar?.setTitle(R.string.nc_forward_to_three_dots) } else { - val activity = activity as MainActivity? searchItem!!.isVisible = conversationItems.size > 0 - if (activity != null) { - if (adapter!!.hasFilter()) { - showSearchView(activity, searchView, searchItem) - searchView!!.setQuery(adapter!!.getFilter(String::class.java), false) - } - activity.binding.searchText.setOnClickListener { - showSearchView(activity, searchView, searchItem) - viewThemeUtils.platform.themeStatusBar(activity, searchView!!) - } + if (adapter!!.hasFilter()) { + showSearchView(searchView, searchItem) + searchView!!.setQuery(adapter!!.getFilter(String::class.java), false) + } + binding.searchText.setOnClickListener { + showSearchView(searchView, searchItem) + viewThemeUtils.platform.themeStatusBar(this, searchView!!) } searchView!!.setOnCloseListener { if (TextUtils.isEmpty(searchView!!.query.toString())) { searchView!!.onActionViewCollapsed() - if (activity != null) { - viewThemeUtils.platform.resetStatusBar(activity) - } + viewThemeUtils.platform.resetStatusBar(this) } else { searchView!!.post { searchView!!.setQuery(TAG, true) } } @@ -428,48 +433,118 @@ class ConversationsListController(bundle: Bundle) : } binding?.swipeRefreshLayoutView?.isEnabled = true searchView!!.onActionViewCollapsed() - val mainActivity = getActivity() as MainActivity? - if (mainActivity != null) { - mainActivity.binding.appBar.stateListAnimator = AnimatorInflater.loadStateListAnimator( - mainActivity.binding.appBar.context, - R.animator.appbar_elevation_off - ) - mainActivity.binding.toolbar.visibility = View.GONE - mainActivity.binding.searchToolbar.visibility = View.VISIBLE - if (resources != null) { - viewThemeUtils.platform - .resetStatusBar(mainActivity) - } + + binding.conversationListAppbar.stateListAnimator = AnimatorInflater.loadStateListAnimator( + binding.conversationListAppbar.context, + R.animator.appbar_elevation_off + ) + binding.conversationListToolbar.visibility = View.GONE + binding.searchToolbar.visibility = View.VISIBLE + if (resources != null) { + viewThemeUtils.platform.resetStatusBar(this@ConversationsListActivity) } + val layoutManager = binding?.recyclerView?.layoutManager as SmoothScrollLinearLayoutManager? layoutManager?.scrollToPositionWithOffset(0, 0) return true } }) } + return true + } + + private fun showSearchOrToolbar() { + if (TextUtils.isEmpty(searchQuery)) { + val showSearchBar = appBarLayoutType == AppBarLayoutType.SEARCH_BAR + + if (appBarLayoutType == AppBarLayoutType.EMPTY) { + hideBars() + } else { + if (showSearchBar) { + showSearchBar() + } else { + showToolbar() + } + colorizeStatusBar(showSearchBar, this, resources) + } + colorizeNavigationBar(this, resources) + } + } + + private fun showSearchBar() { + val layoutParams = binding.searchToolbar.layoutParams as AppBarLayout.LayoutParams + binding.searchToolbar.visibility = View.VISIBLE + binding.searchText.hint = getString(R.string.appbar_search_in, getString(R.string.nc_app_product_name)) + binding.conversationListToolbar.visibility = View.GONE + // layoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout + // .LayoutParams.SCROLL_FLAG_SNAP | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); + layoutParams.scrollFlags = 0 + binding.conversationListAppbar.stateListAnimator = AnimatorInflater.loadStateListAnimator( + binding.conversationListAppbar.context, + R.animator.appbar_elevation_off + ) + binding.searchToolbar.layoutParams = layoutParams + } + + private fun showToolbar() { + val layoutParams = binding.searchToolbar.layoutParams as AppBarLayout.LayoutParams + binding.searchToolbar.visibility = View.GONE + binding.searchToolbar.visibility = View.VISIBLE + viewThemeUtils.material.colorToolbarOverflowIcon(binding.conversationListToolbar) + layoutParams.scrollFlags = 0 + binding.conversationListAppbar.stateListAnimator = AnimatorInflater.loadStateListAnimator( + binding.conversationListAppbar.context, + R.animator.appbar_elevation_on + ) + binding.conversationListToolbar.layoutParams = layoutParams + } + + private fun hideBars() { + binding.conversationListToolbar.visibility = View.GONE + binding.searchToolbar.visibility = View.GONE + } + + private fun hideSearchBar() { + val layoutParams = binding.searchToolbar.layoutParams as AppBarLayout.LayoutParams + binding.searchToolbar.visibility = View.GONE + binding.conversationListToolbar.visibility = View.VISIBLE + layoutParams.scrollFlags = 0 + binding.conversationListAppbar.stateListAnimator = AnimatorInflater.loadStateListAnimator( + binding.conversationListAppbar.context, + R.animator.appbar_elevation_on + ) + } + + private fun colorizeStatusBar(showSearchBar: Boolean, activity: Activity?, resources: Resources?) { + if (activity != null && resources != null) { + if (showSearchBar) { + viewThemeUtils.platform.resetStatusBar(activity) + } else { + viewThemeUtils.platform.themeStatusBar(activity, binding.root) + } + } + } + + private fun colorizeNavigationBar(activity: Activity?, resources: Resources?) { + if (activity != null && resources != null) { + DisplayUtils.applyColorToNavigationBar( + activity.window, + ResourcesCompat.getColor(resources, R.color.bg_default, null) + ) + } } private fun hasActivityActionSendIntent(): Boolean { - return if (activity != null) { - Intent.ACTION_SEND == activity!!.intent.action || Intent.ACTION_SEND_MULTIPLE == activity!!.intent.action - } else { - false - } + return Intent.ACTION_SEND == intent.action || Intent.ACTION_SEND_MULTIPLE == intent.action } - override fun showSearchOrToolbar() { - if (TextUtils.isEmpty(searchQuery)) { - super.showSearchOrToolbar() - } - } - - private fun showSearchView(activity: MainActivity, searchView: SearchView?, searchItem: MenuItem?) { - activity.binding.appBar.stateListAnimator = AnimatorInflater.loadStateListAnimator( - activity.binding.appBar.context, + private fun showSearchView(searchView: SearchView?, searchItem: MenuItem?) { + binding.conversationListAppbar.stateListAnimator = AnimatorInflater.loadStateListAnimator( + binding.conversationListAppbar.context, R.animator.appbar_elevation_on ) - activity.binding.toolbar.visibility = View.VISIBLE - activity.binding.searchToolbar.visibility = View.GONE + binding.conversationListToolbar.visibility = View.VISIBLE + binding.searchToolbar.visibility = View.GONE searchItem!!.expandActionView() } @@ -499,10 +574,11 @@ class ConversationsListController(bundle: Bundle) : // This is invoked asynchronously, when server returns a response the view might have been // unbound in the meantime. Check if the view is still there. // FIXME - does it make sense to update internal data structures even when view has been unbound? - if (view == null) { - Log.d(TAG, "fetchData - getRooms - view is not bound: $startNanoTime") - return@subscribe - } + // if (view == null) { + // Log.d(TAG, "fetchData - getRooms - view is not bound: $startNanoTime") + // return@subscribe + // } + if (adapterWasNull) { adapterWasNull = false binding?.loadingContent?.visibility = View.GONE @@ -548,8 +624,8 @@ class ConversationsListController(bundle: Bundle) : } private fun addToConversationItems(conversation: Conversation) { - if (bundle.containsKey(KEY_FORWARD_HIDE_SOURCE_ROOM) && conversation.roomId == - bundle.getString(KEY_FORWARD_HIDE_SOURCE_ROOM) + if (intent.getStringExtra(KEY_FORWARD_HIDE_SOURCE_ROOM) != null && + intent.getStringExtra(KEY_FORWARD_HIDE_SOURCE_ROOM) == conversation.roomId ) { return } @@ -566,23 +642,22 @@ class ConversationsListController(bundle: Bundle) : genericTextHeaderItem = GenericTextHeaderItem(headerTitle, viewThemeUtils) callHeaderItems[headerTitle] = genericTextHeaderItem } - if (activity != null) { - val conversationItem = ConversationItem( - conversation, - currentUser!!, - activity!!, - viewThemeUtils - ) - conversationItems.add(conversationItem) - val conversationItemWithHeader = ConversationItem( - conversation, - currentUser!!, - activity!!, - callHeaderItems[headerTitle], - viewThemeUtils - ) - conversationItemsWithHeader.add(conversationItemWithHeader) - } + + val conversationItem = ConversationItem( + conversation, + currentUser!!, + this, + viewThemeUtils + ) + conversationItems.add(conversationItem) + val conversationItemWithHeader = ConversationItem( + conversation, + currentUser!!, + this, + callHeaderItems[headerTitle], + viewThemeUtils + ) + conversationItemsWithHeader.add(conversationItemWithHeader) } private fun showErrorDialog() { @@ -639,7 +714,7 @@ class ConversationsListController(bundle: Bundle) : val conversationItem = ConversationItem( conversation, currentUser!!, - activity!!, + this, callHeaderItems[headerTitle], viewThemeUtils ) @@ -659,30 +734,18 @@ class ConversationsListController(bundle: Bundle) : private fun handleHttpExceptions(throwable: Throwable) { if (throwable is HttpException) { when (throwable.code()) { - HTTP_UNAUTHORIZED -> if (parentController != null && parentController!!.router != null) { - Log.d(TAG, "Starting reauth webview via getParentController()") - parentController!!.router.pushController( - RouterTransaction.with( - WebViewLoginController( - currentUser!!.baseUrl, - true - ) - ) - .pushChangeHandler(VerticalChangeHandler()) - .popChangeHandler(VerticalChangeHandler()) - ) - } else { - Log.d(TAG, "Starting reauth webview via ConversationsListController") - showUnauthorizedDialog() + HTTP_UNAUTHORIZED -> showUnauthorizedDialog() + else -> { + Log.e(TAG, "Http exception in ConversationListActivity", throwable) + Toast.makeText(context, R.string.nc_common_error_sorry, Toast.LENGTH_LONG).show() } - else -> {} } } } @SuppressLint("ClickableViewAccessibility") private fun prepareViews() { - layoutManager = SmoothScrollLinearLayoutManager(Objects.requireNonNull(activity)) + layoutManager = SmoothScrollLinearLayoutManager(this) binding?.recyclerView?.layoutManager = layoutManager binding?.recyclerView?.setHasFixedSize(true) binding?.recyclerView?.adapter = adapter @@ -695,8 +758,8 @@ class ConversationsListController(bundle: Bundle) : } }) binding?.recyclerView?.setOnTouchListener { v: View, _: MotionEvent? -> - if (isAttached && (!isBeingDestroyed || !isDestroyed)) { - val imm = activity!!.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + if (!isDestroyed) { + val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager imm.hideSoftInputFromWindow(v.windowToken, 0) } false @@ -709,21 +772,17 @@ class ConversationsListController(bundle: Bundle) : showNewConversationsScreen() } binding?.floatingActionButton?.let { viewThemeUtils.material.themeFAB(it) } - if (activity != null && activity is MainActivity) { - val activity = activity as MainActivity? - activity!!.binding.switchAccountButton.setOnClickListener { - if (resources != null && resources!!.getBoolean(R.bool.multiaccount_support)) { - val newFragment: DialogFragment = ChooseAccountDialogFragment.newInstance() - newFragment.show( - (getActivity() as MainActivity?)!!.supportFragmentManager, - ChooseAccountDialogFragment.TAG - ) - } else { - val intent = Intent(context, SettingsActivity::class.java) - startActivity(intent) - } + + binding.switchAccountButton.setOnClickListener { + if (resources != null && resources!!.getBoolean(R.bool.multiaccount_support)) { + val newFragment: DialogFragment = ChooseAccountDialogFragment.newInstance() + newFragment.show(supportFragmentManager, ChooseAccountDialogFragment.TAG) + } else { + val intent = Intent(context, SettingsActivity::class.java) + startActivity(intent) } } + binding?.newMentionPopupBubble?.hide() binding?.newMentionPopupBubble?.setPopupBubbleListener { binding?.recyclerView?.smoothScrollToPosition( @@ -786,17 +845,19 @@ class ConversationsListController(bundle: Bundle) : } } - public override fun onSaveViewState(view: View, outState: Bundle) { + override fun onSaveInstanceState(bundle: Bundle) { + super.onSaveInstanceState(bundle) + if (searchView != null && !TextUtils.isEmpty(searchView!!.query)) { - outState.putString(KEY_SEARCH_QUERY, searchView!!.query.toString()) + bundle.putString(KEY_SEARCH_QUERY, searchView!!.query.toString()) } - super.onSaveViewState(view, outState) } - public override fun onRestoreViewState(view: View, savedViewState: Bundle) { - super.onRestoreViewState(view, savedViewState) - if (savedViewState.containsKey(KEY_SEARCH_QUERY)) { - searchQuery = savedViewState.getString(KEY_SEARCH_QUERY, "") + override fun onRestoreInstanceState(savedInstanceState: Bundle) { + super.onRestoreInstanceState(savedInstanceState) + + if (savedInstanceState.containsKey(KEY_SEARCH_QUERY)) { + searchQuery = savedInstanceState.getString(KEY_SEARCH_QUERY, "") } } @@ -906,7 +967,7 @@ class ConversationsListController(bundle: Bundle) : @Suppress("Detekt.ComplexMethod") private fun handleConversation(conversation: Conversation?) { selectedConversation = conversation - if (selectedConversation != null && activity != null) { + if (selectedConversation != null) { val hasChatPermission = ParticipantPermissions(currentUser!!, selectedConversation!!).hasChatPermission() if (showShareToScreen) { if (hasChatPermission && @@ -919,7 +980,7 @@ class ConversationsListController(bundle: Bundle) : } } else if (forwardMessage) { if (hasChatPermission && !isReadOnlyConversation(selectedConversation!!)) { - openConversation(bundle.getString(KEY_FORWARD_MSG_TEXT)) + openConversation(intent.getStringExtra(KEY_FORWARD_MSG_TEXT)) forwardMessage = false } else { Toast.makeText(context, R.string.send_to_forbidden, Toast.LENGTH_LONG).show() @@ -1001,7 +1062,7 @@ class ConversationsListController(bundle: Bundle) : } private fun clearIntentAction() { - activity!!.intent.action = "" + intent.action = "" } override fun onItemLongClick(position: Int) { @@ -1012,7 +1073,7 @@ class ConversationsListController(bundle: Bundle) : if (clickedItem != null) { val conversation = (clickedItem as ConversationItem).model conversationsListBottomDialog = ConversationsListBottomDialog( - activity!!, + this, this, userManager.currentUser.blockingGet(), conversation @@ -1025,8 +1086,7 @@ class ConversationsListController(bundle: Bundle) : @Suppress("Detekt.TooGenericExceptionCaught") private fun collectDataFromIntent() { filesToShare = ArrayList() - if (activity != null && activity!!.intent != null) { - val intent = activity!!.intent + if (intent != null) { if (Intent.ACTION_SEND == intent.action || Intent.ACTION_SEND_MULTIPLE == intent.action) { try { val mimeType = intent.type @@ -1099,6 +1159,7 @@ class ConversationsListController(bundle: Bundle) : } override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == UploadAndShareFilesWorker.REQUEST_PERMISSION && grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED @@ -1132,13 +1193,6 @@ class ConversationsListController(bundle: Bundle) : bundle.putString(BundleKeys.KEY_MESSAGE_ID, selectedMessageId) selectedMessageId = null } - // remapChatController( - // router, - // currentUser!!.id!!, - // selectedConversation!!.token!!, - // bundle, - // false - // ) val intent = Intent(context, ChatActivity::class.java) intent.putExtras(bundle) @@ -1171,8 +1225,7 @@ class ConversationsListController(bundle: Bundle) : override fun showDeleteConversationDialog(bundle: Bundle) { conversationMenuBundle = bundle - if (activity != null && - conversationMenuBundle != null && + if (conversationMenuBundle != null && isInternalUserEqualsCurrentUser(currentUser, conversationMenuBundle) ) { val conversation = Parcels.unwrap(conversationMenuBundle!!.getParcelable(KEY_ROOM)) @@ -1216,53 +1269,47 @@ class ConversationsListController(bundle: Bundle) : } private fun showUnauthorizedDialog() { - if (activity != null) { - binding?.floatingActionButton?.let { - val dialogBuilder = MaterialAlertDialogBuilder(it.context) - .setIcon( - viewThemeUtils.dialog.colorMaterialAlertDialogIcon( - context, - R.drawable.ic_delete_black_24dp - ) + binding?.floatingActionButton?.let { + val dialogBuilder = MaterialAlertDialogBuilder(it.context) + .setIcon( + viewThemeUtils.dialog.colorMaterialAlertDialogIcon( + context, + R.drawable.ic_delete_black_24dp ) - .setTitle(R.string.nc_dialog_invalid_password) - .setMessage(R.string.nc_dialog_reauth_or_delete) - .setCancelable(false) - .setPositiveButton(R.string.nc_delete) { _, _ -> - val otherUserExists = userManager - .scheduleUserForDeletionWithId(currentUser!!.id!!) - .blockingGet() - val accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java).build() - WorkManager.getInstance().enqueue(accountRemovalWork) - if (otherUserExists && view != null) { - onViewBound(view!!) - onAttach(view!!) - } else if (!otherUserExists) { - router.setRoot( - RouterTransaction.with(ServerSelectionController()) - .pushChangeHandler(VerticalChangeHandler()) - .popChangeHandler(VerticalChangeHandler()) - ) - } - } - .setNegativeButton(R.string.nc_settings_reauthorize) { _, _ -> - router.pushController( - RouterTransaction.with( - WebViewLoginController(currentUser!!.baseUrl, true) - ) - .pushChangeHandler(VerticalChangeHandler()) - .popChangeHandler(VerticalChangeHandler()) - ) - } - - 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_dialog_invalid_password) + .setMessage(R.string.nc_dialog_reauth_or_delete) + .setCancelable(false) + .setPositiveButton(R.string.nc_delete) { _, _ -> + val otherUserExists = userManager + .scheduleUserForDeletionWithId(currentUser!!.id!!) + .blockingGet() + val accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java).build() + WorkManager.getInstance().enqueue(accountRemovalWork) + if (otherUserExists) { + finish() + startActivity(intent) + } else if (!otherUserExists) { + Log.d(TAG, "No other users found. AccountRemovalWorker will restart the app.") + } + } + .setNegativeButton(R.string.nc_settings_reauthorize) { _, _ -> + // TODO + // router.pushController( + // RouterTransaction.with( + // WebViewLoginController(currentUser!!.baseUrl, true) + // ) + // .pushChangeHandler(VerticalChangeHandler()) + // .popChangeHandler(VerticalChangeHandler()) + // ) + } + + viewThemeUtils.dialog.colorMaterialAlertDialogBackground(it.context, dialogBuilder) + val dialog = dialogBuilder.show() + viewThemeUtils.platform.colorTextButtons( + dialog.getButton(AlertDialog.BUTTON_POSITIVE), + dialog.getButton(AlertDialog.BUTTON_NEGATIVE) + ) } } @@ -1279,25 +1326,20 @@ class ConversationsListController(bundle: Bundle) : .blockingGet() val accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java).build() WorkManager.getInstance().enqueue(accountRemovalWork) - if (otherUserExists && view != null) { - onViewBound(view!!) - onAttach(view!!) + if (otherUserExists) { + finish() + startActivity(intent) } else if (!otherUserExists) { - router.setRoot( - RouterTransaction.with( - ServerSelectionController() - ) - .pushChangeHandler(VerticalChangeHandler()) - .popChangeHandler(VerticalChangeHandler()) - ) + restartApp(this) } } .setNegativeButton(R.string.nc_cancel) { _, _ -> if (userManager.users.blockingGet().isNotEmpty()) { - router.pushController(RouterTransaction.with(SwitchAccountController())) + // TODO + // router.pushController(RouterTransaction.with(SwitchAccountController())) } else { - activity!!.finishAffinity() - activity!!.finish() + finishAffinity() + finish() } } @@ -1310,6 +1352,15 @@ class ConversationsListController(bundle: Bundle) : } } + fun restartApp(context: Context) { + val packageManager = context.packageManager + val intent = packageManager.getLaunchIntentForPackage(context.packageName) + val componentName = intent!!.component + val mainIntent = Intent.makeRestartActivityTask(componentName) + context.startActivity(mainIntent) + Runtime.getRuntime().exit(0) + } + private fun deleteConversation(data: Data) { val deleteConversationWorker = OneTimeWorkRequest.Builder(DeleteConversationWorker::class.java).setInputData(data).build() @@ -1351,6 +1402,13 @@ class ConversationsListController(bundle: Bundle) : showErrorDialog() } + override fun onBackPressed() { + super.onBackPressed() + + // TODO: replace this when conductor is removed. For now it avoids to load the MainActiviy which has no UI. + finishAffinity() + } + companion object { const val TAG = "ConvListController" const val UNREAD_BUBBLE_DELAY = 2500 @@ -1360,10 +1418,4 @@ class ConversationsListController(bundle: Bundle) : const val SEARCH_MIN_CHARS = 2 const val HTTP_UNAUTHORIZED = 401 } - - init { - setHasOptionsMenu(true) - forwardMessage = bundle.getBoolean(KEY_FORWARD_MSG_FLAG) - this.bundle = bundle - } } diff --git a/app/src/main/java/com/nextcloud/talk/messagesearch/MessageSearchActivity.kt b/app/src/main/java/com/nextcloud/talk/messagesearch/MessageSearchActivity.kt index e54baa6aa..3f4600810 100644 --- a/app/src/main/java/com/nextcloud/talk/messagesearch/MessageSearchActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/messagesearch/MessageSearchActivity.kt @@ -38,7 +38,7 @@ import com.nextcloud.talk.activities.BaseActivity import com.nextcloud.talk.adapters.items.LoadMoreResultsItem import com.nextcloud.talk.adapters.items.MessageResultItem import com.nextcloud.talk.application.NextcloudTalkApplication -import com.nextcloud.talk.controllers.ConversationsListController +import com.nextcloud.talk.conversationlist.ConversationsListActivity import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.databinding.ActivityMessageSearchBinding import com.nextcloud.talk.utils.DisplayUtils @@ -241,7 +241,7 @@ class MessageSearchActivity : BaseActivity() { when { TextUtils.isEmpty(query) -> Observable.empty() else -> Observable.timer( - ConversationsListController.SEARCH_DEBOUNCE_INTERVAL_MS.toLong(), + ConversationsListActivity.SEARCH_DEBOUNCE_INTERVAL_MS.toLong(), TimeUnit.MILLISECONDS ) } diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java b/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java index 6007db129..a6c65d0c1 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java +++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java @@ -26,6 +26,7 @@ package com.nextcloud.talk.ui.dialog; import android.annotation.SuppressLint; import android.app.Dialog; +import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.util.Log; @@ -34,16 +35,17 @@ import android.view.View; import android.view.ViewGroup; import com.google.android.material.dialog.MaterialAlertDialogBuilder; -import com.nextcloud.talk.activities.MainActivity; import com.nextcloud.talk.adapters.items.AdvancedUserItem; import com.nextcloud.talk.api.NcApi; import com.nextcloud.talk.application.NextcloudTalkApplication; +import com.nextcloud.talk.conversationlist.ConversationsListActivity; import com.nextcloud.talk.data.user.model.User; import com.nextcloud.talk.databinding.DialogChooseAccountBinding; import com.nextcloud.talk.extensions.ImageViewExtensionsKt; import com.nextcloud.talk.models.json.participants.Participant; import com.nextcloud.talk.models.json.status.Status; import com.nextcloud.talk.models.json.status.StatusOverall; +import com.nextcloud.talk.settings.SettingsActivity; import com.nextcloud.talk.ui.StatusDrawable; import com.nextcloud.talk.ui.theme.ViewThemeUtils; import com.nextcloud.talk.users.UserManager; @@ -178,16 +180,18 @@ public class ChooseAccountDialogFragment extends DialogFragment { // Creating listeners for quick-actions binding.currentAccount.getRoot().setOnClickListener(v -> dismiss()); - if (getActivity() instanceof MainActivity) { - binding.addAccount.setOnClickListener(v -> { - dismiss(); - ((MainActivity) getActivity()).addAccount(); - }); - binding.manageSettings.setOnClickListener(v -> { - dismiss(); - ((MainActivity) getActivity()).openSettings(); - }); - } + + binding.addAccount.setOnClickListener(v -> { + dismiss(); + // TODO +// ((MainActivity) getActivity()).addAccount(); + }); + binding.manageSettings.setOnClickListener(v -> { + Intent intent = new Intent(getContext(), SettingsActivity.class); + startActivity(intent); + dismiss(); + }); + binding.setStatus.setOnClickListener(v -> { dismiss(); @@ -294,10 +298,14 @@ public class ChooseAccountDialogFragment extends DialogFragment { if (userManager.setUserAsActive(user).blockingGet()) { cookieManager.getCookieStore().removeAll(); - if (getActivity() != null) { - getActivity().runOnUiThread( - () -> ((MainActivity) getActivity()).resetConversationsList()); - } + + Intent intent = new Intent(getContext(), ConversationsListActivity.class); + // TODO: might be better with FLAG_ACTIVITY_SINGLE_TOP instead than FLAG_ACTIVITY_CLEAR_TOP to + // have a smoother transition. However the handling in onNewIntent() in + // ConversationListActivity must be improved for this. + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(intent); + dismiss(); } } diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/ConversationsListBottomDialog.kt b/app/src/main/java/com/nextcloud/talk/ui/dialog/ConversationsListBottomDialog.kt index abc87eaf6..1113fa0f6 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/dialog/ConversationsListBottomDialog.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/ConversationsListBottomDialog.kt @@ -38,7 +38,6 @@ import com.google.android.material.bottomsheet.BottomSheetDialog import com.nextcloud.talk.R import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.application.NextcloudTalkApplication -import com.nextcloud.talk.controllers.ConversationsListController import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_ADD_FAVORITE import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_MARK_AS_READ @@ -47,6 +46,7 @@ import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_ import com.nextcloud.talk.controllers.bottomsheet.ConversationOperationEnum.OPS_CODE_RENAME_ROOM import com.nextcloud.talk.controllers.bottomsheet.EntryMenuController import com.nextcloud.talk.controllers.bottomsheet.OperationsMenuController +import com.nextcloud.talk.conversationlist.ConversationsListActivity import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.databinding.DialogConversationOperationsBinding import com.nextcloud.talk.jobs.LeaveConversationWorker @@ -64,7 +64,7 @@ import javax.inject.Inject @AutoInjector(NextcloudTalkApplication::class) class ConversationsListBottomDialog( val activity: Activity, - val controller: ConversationsListController, + val controller: ConversationsListActivity, val currentUser: User, val conversation: Conversation ) : BottomSheetDialog(activity) { diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 430439fdb..97c8575c0 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -40,87 +40,7 @@ android:windowContentOverlay="@null" app:elevation="0dp"> - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + android:orientation="vertical" + android:layout_marginTop="50dp">