diff --git a/library/ui-styles/build.gradle b/library/ui-styles/build.gradle index eabd0f36f6..c85f26dbc4 100644 --- a/library/ui-styles/build.gradle +++ b/library/ui-styles/build.gradle @@ -53,6 +53,7 @@ android { dependencies { implementation libs.androidx.appCompat + implementation libs.androidx.fragmentKtx implementation libs.google.material // Pref theme implementation libs.androidx.preferenceKtx diff --git a/library/ui-styles/src/debug/java/im/vector/lib/ui/styles/debug/DebugMaterialThemeActivity.kt b/library/ui-styles/src/debug/java/im/vector/lib/ui/styles/debug/DebugMaterialThemeActivity.kt index 553d495e22..412d6fdc1c 100644 --- a/library/ui-styles/src/debug/java/im/vector/lib/ui/styles/debug/DebugMaterialThemeActivity.kt +++ b/library/ui-styles/src/debug/java/im/vector/lib/ui/styles/debug/DebugMaterialThemeActivity.kt @@ -18,8 +18,12 @@ package im.vector.lib.ui.styles.debug import android.os.Bundle import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem import android.widget.Toast import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.MenuProvider +import androidx.lifecycle.Lifecycle import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.Snackbar import im.vector.lib.ui.styles.R @@ -31,6 +35,7 @@ abstract class DebugMaterialThemeActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + setupMenu() val views = ActivityDebugMaterialThemeBinding.inflate(layoutInflater) setContentView(views.root) @@ -72,6 +77,27 @@ abstract class DebugMaterialThemeActivity : AppCompatActivity() { } } + private fun setupMenu() { + addMenuProvider( + object : MenuProvider { + override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) { + menuInflater.inflate(R.menu.menu_debug, menu) + } + + override fun onMenuItemSelected(menuItem: MenuItem): Boolean { + Toast.makeText( + this@DebugMaterialThemeActivity, + "Menu ${menuItem.title} clicked!", + Toast.LENGTH_SHORT + ).show() + return true + } + }, + this, + Lifecycle.State.RESUMED + ) + } + private fun showTestDialog(theme: Int) { MaterialAlertDialogBuilder(this, theme) .setTitle("Dialog title") @@ -82,9 +108,4 @@ abstract class DebugMaterialThemeActivity : AppCompatActivity() { .setNeutralButton("Neutral", null) .show() } - - override fun onCreateOptionsMenu(menu: Menu): Boolean { - menuInflater.inflate(R.menu.menu_debug, menu) - return true - } } diff --git a/tools/check/forbidden_strings_in_code.txt b/tools/check/forbidden_strings_in_code.txt index 962a14843d..b12f15fa5d 100755 --- a/tools/check/forbidden_strings_in_code.txt +++ b/tools/check/forbidden_strings_in_code.txt @@ -180,3 +180,8 @@ System\.currentTimeMillis\(\)===2 ### Remove extra space between the name and the description \* @\w+ \w+ + + +### Please use the MenuProvider interface now +onCreateOptionsMenu +onOptionsItemSelected +onPrepareOptionsMenu diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt b/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt index 66b613d292..825b94fd5d 100644 --- a/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt +++ b/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt @@ -24,6 +24,7 @@ import android.os.Build import android.os.Bundle import android.os.Parcelable import android.view.Menu +import android.view.MenuInflater import android.view.MenuItem import android.view.View import android.view.WindowInsetsController @@ -36,10 +37,12 @@ import androidx.annotation.StringRes import androidx.appcompat.app.AppCompatActivity import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.content.ContextCompat +import androidx.core.view.MenuProvider import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentFactory import androidx.fragment.app.FragmentManager +import androidx.lifecycle.Lifecycle import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding @@ -199,6 +202,7 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver supportFragmentManager.fragmentFactory = fragmentFactory viewModelFactory = activityEntryPoint.viewModelFactory() super.onCreate(savedInstanceState) + setupMenu() configurationViewModel = viewModelProvider.get(ConfigurationViewModel::class.java) bugReporter = singletonEntryPoint.bugReporter() pinLocker = singletonEntryPoint.pinLocker() @@ -249,6 +253,30 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver } } + private fun setupMenu() { + // Always add a MenuProvider to handle the back action from the Toolbar + addMenuProvider( + object : MenuProvider { + override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) { + getMenuRes() + .takeIf { it != -1 } + ?.let { menuInflater.inflate(it, menu) } + handlePostCreateMenu(menu) + } + + override fun onPrepareMenu(menu: Menu) { + handlePrepareMenu(menu) + } + + override fun onMenuItemSelected(menuItem: MenuItem): Boolean { + return handleMenuItemSelected(menuItem) + } + }, + this, + Lifecycle.State.RESUMED + ) + } + /** * This method has to be called for the font size setting be supported correctly. */ @@ -467,24 +495,24 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver * MENU MANAGEMENT * ========================================================================================== */ - override fun onCreateOptionsMenu(menu: Menu): Boolean { - val menuRes = getMenuRes() + @MenuRes + open fun getMenuRes() = -1 - if (menuRes != -1) { - menuInflater.inflate(menuRes, menu) - return true + // No op by default + open fun handlePostCreateMenu(menu: Menu) = Unit + + // No op by default + open fun handlePrepareMenu(menu: Menu) = Unit + + @CallSuper + open fun handleMenuItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + android.R.id.home -> { + onBackPressed(true) + true + } + else -> false } - - return super.onCreateOptionsMenu(menu) - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - if (item.itemId == android.R.id.home) { - onBackPressed(true) - return true - } - - return super.onOptionsItemSelected(item) } override fun onBackPressed() { @@ -587,9 +615,6 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver @StringRes open fun getTitleRes() = -1 - @MenuRes - open fun getMenuRes() = -1 - /** * Return a object containing other themes for this activity. */ diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt b/vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt index 38667b774f..a1fd774757 100644 --- a/vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt +++ b/vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt @@ -22,12 +22,16 @@ import android.os.Parcelable import android.view.LayoutInflater import android.view.Menu import android.view.MenuInflater +import android.view.MenuItem import android.view.View import android.view.ViewGroup import androidx.annotation.CallSuper import androidx.annotation.MainThread import androidx.appcompat.app.AlertDialog +import androidx.core.view.MenuHost +import androidx.core.view.MenuProvider import androidx.fragment.app.Fragment +import androidx.lifecycle.Lifecycle import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding @@ -126,9 +130,7 @@ abstract class VectorBaseFragment : Fragment(), MavericksView @CallSuper override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - if (getMenuRes() != -1) { - setHasOptionsMenu(true) - } + Timber.i("onCreate Fragment ${javaClass.simpleName}") } final override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { @@ -158,6 +160,30 @@ abstract class VectorBaseFragment : Fragment(), MavericksView override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) Timber.i("onViewCreated Fragment ${javaClass.simpleName}") + setupMenu() + } + + private fun setupMenu() { + val menuRes = getMenuRes().takeIf { it != -1 } ?: return + val menuHost: MenuHost = requireActivity() + menuHost.addMenuProvider( + object : MenuProvider { + override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) { + menuInflater.inflate(menuRes, menu) + handlePostCreateMenu(menu) + } + + override fun onPrepareMenu(menu: Menu) { + handlePrepareMenu(menu) + } + + override fun onMenuItemSelected(menuItem: MenuItem): Boolean { + return handleMenuItemSelected(menuItem) + } + }, + viewLifecycleOwner, + Lifecycle.State.RESUMED + ) } open fun showLoading(message: CharSequence?) { @@ -272,12 +298,14 @@ abstract class VectorBaseFragment : Fragment(), MavericksView open fun getMenuRes() = -1 - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - val menuRes = getMenuRes() + // No op by default + open fun handlePostCreateMenu(menu: Menu) = Unit - if (menuRes != -1) { - inflater.inflate(menuRes, menu) - } + // No op by default + open fun handlePrepareMenu(menu: Menu) = Unit + + open fun handleMenuItemSelected(item: MenuItem): Boolean { + throw NotImplementedError("You must override this method to handle click on menu item") } // This should be provided by the framework diff --git a/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewFragment.kt b/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewFragment.kt index dfe74fa47e..5a4905942b 100644 --- a/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewFragment.kt @@ -97,7 +97,7 @@ class AttachmentsPreviewFragment @Inject constructor( } } - override fun onOptionsItemSelected(item: MenuItem): Boolean { + override fun handleMenuItemSelected(item: MenuItem): Boolean { return when (item.itemId) { R.id.attachmentsPreviewRemoveAction -> { handleRemoveAction() @@ -107,20 +107,16 @@ class AttachmentsPreviewFragment @Inject constructor( handleEditAction() true } - else -> { - super.onOptionsItemSelected(item) - } + else -> false } } - override fun onPrepareOptionsMenu(menu: Menu) { + override fun handlePrepareMenu(menu: Menu) { withState(viewModel) { state -> val editMenuItem = menu.findItem(R.id.attachmentsPreviewEditAction) val showEditMenuItem = state.attachments.getOrNull(state.currentAttachmentIndex)?.isEditable().orFalse() editMenuItem.setVisible(showEditMenuItem) } - - super.onPrepareOptionsMenu(menu) } override fun getMenuRes() = R.menu.vector_attachments_preview diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt index 579a5851c6..aefde07214 100644 --- a/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt +++ b/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt @@ -214,16 +214,19 @@ class VectorCallActivity : VectorBaseActivity(), CallContro renderState(it) } - override fun onOptionsItemSelected(item: MenuItem): Boolean { - if (item.itemId == R.id.menu_call_open_chat) { - returnToChat() - return true - } else if (item.itemId == android.R.id.home) { - // We check here as we want PiP in some cases - onBackPressed() - return true + override fun handleMenuItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.menu_call_open_chat -> { + returnToChat() + true + } + android.R.id.home -> { + // We check here as we want PiP in some cases + onBackPressed() + true + } + else -> super.handleMenuItemSelected(item) } - return super.onOptionsItemSelected(item) } override fun onDestroy() { diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupActivity.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupActivity.kt index 7478adb165..077bcc2cf3 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupActivity.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupActivity.kt @@ -187,16 +187,6 @@ class KeysBackupSetupActivity : SimpleFragmentActivity() { } } -// I think this code is useful, but it violates the code quality rules -// override fun onOptionsItemSelected(item: MenuItem): Boolean { -// if (item.itemId == android .R. id. home) { -// onBackPressed() -// return true -// } -// -// return super.onOptionsItemSelected(item) -// } - companion object { const val KEYS_VERSION = "KEYS_VERSION" const val MANUAL_EXPORT = "MANUAL_EXPORT" diff --git a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolActivity.kt b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolActivity.kt index 6225741310..88499c7531 100644 --- a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolActivity.kt +++ b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolActivity.kt @@ -133,16 +133,18 @@ class RoomDevToolActivity : SimpleFragmentActivity(), FragmentManager.OnBackStac } } - override fun onOptionsItemSelected(item: MenuItem): Boolean { - if (item.itemId == R.id.menuItemEdit) { - viewModel.handle(RoomDevToolAction.MenuEdit) - return true + override fun handleMenuItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.menuItemEdit -> { + viewModel.handle(RoomDevToolAction.MenuEdit) + true + } + R.id.menuItemSend -> { + viewModel.handle(RoomDevToolAction.MenuItemSend) + true + } + else -> super.handleMenuItemSelected(item) } - if (item.itemId == R.id.menuItemSend) { - viewModel.handle(RoomDevToolAction.MenuItemSend) - return true - } - return super.onOptionsItemSelected(item) } override fun onBackPressed() { @@ -174,21 +176,22 @@ class RoomDevToolActivity : SimpleFragmentActivity(), FragmentManager.OnBackStac super.onDestroy() } - override fun onPrepareOptionsMenu(menu: Menu): Boolean = withState(viewModel) { state -> - menu.forEach { - val isVisible = when (it.itemId) { - R.id.menuItemEdit -> { - state.displayMode is RoomDevToolViewState.Mode.StateEventDetail + override fun handlePrepareMenu(menu: Menu) { + withState(viewModel) { state -> + menu.forEach { + val isVisible = when (it.itemId) { + R.id.menuItemEdit -> { + state.displayMode is RoomDevToolViewState.Mode.StateEventDetail + } + R.id.menuItemSend -> { + state.displayMode is RoomDevToolViewState.Mode.EditEventContent || + state.displayMode is RoomDevToolViewState.Mode.SendEventForm + } + else -> true } - R.id.menuItemSend -> { - state.displayMode is RoomDevToolViewState.Mode.EditEventContent || - state.displayMode is RoomDevToolViewState.Mode.SendEventForm - } - else -> true + it.isVisible = isVisible } - it.isVisible = isVisible } - return@withState true } companion object { diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt index f2690fa18a..82c9c78852 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt @@ -547,47 +547,45 @@ class HomeActivity : override fun getMenuRes() = R.menu.home - override fun onPrepareOptionsMenu(menu: Menu): Boolean { + override fun handlePrepareMenu(menu: Menu) { menu.findItem(R.id.menu_home_init_sync_legacy).isVisible = vectorPreferences.developerMode() menu.findItem(R.id.menu_home_init_sync_optimized).isVisible = vectorPreferences.developerMode() - return super.onPrepareOptionsMenu(menu) } - override fun onOptionsItemSelected(item: MenuItem): Boolean { - when (item.itemId) { + override fun handleMenuItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { R.id.menu_home_suggestion -> { bugReporter.openBugReportScreen(this, ReportType.SUGGESTION) - return true + true } R.id.menu_home_report_bug -> { bugReporter.openBugReportScreen(this, ReportType.BUG_REPORT) - return true + true } R.id.menu_home_init_sync_legacy -> { // Configure the SDK initialSyncStrategy = InitialSyncStrategy.Legacy // And clear cache MainActivity.restartApp(this, MainActivityArgs(clearCache = true)) - return true + true } R.id.menu_home_init_sync_optimized -> { // Configure the SDK initialSyncStrategy = InitialSyncStrategy.Optimized() // And clear cache MainActivity.restartApp(this, MainActivityArgs(clearCache = true)) - return true + true } R.id.menu_home_filter -> { navigator.openRoomsFiltering(this) - return true + true } R.id.menu_home_setting -> { navigator.openSettings(this) - return true + true } + else -> super.handleMenuItemSelected(item) } - - return super.onOptionsItemSelected(item) } override fun onBackPressed() { diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt index 9deae0970b..787c39b3e3 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt @@ -91,23 +91,21 @@ class HomeDetailFragment @Inject constructor( override fun getMenuRes() = R.menu.room_list - override fun onOptionsItemSelected(item: MenuItem): Boolean { - when (item.itemId) { + override fun handleMenuItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { R.id.menu_home_mark_all_as_read -> { viewModel.handle(HomeDetailAction.MarkAllRoomsRead) - return true + true } + else -> false } - - return super.onOptionsItemSelected(item) } - override fun onPrepareOptionsMenu(menu: Menu) { + override fun handlePrepareMenu(menu: Menu) { withState(viewModel) { state -> val isRoomList = state.currentTab is HomeTab.RoomList menu.findItem(R.id.menu_home_mark_all_as_read).isVisible = isRoomList && hasUnreadRooms } - super.onPrepareOptionsMenu(menu) } override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentHomeDetailBinding { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt index 2b99bc67ef..8e2e5468a8 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt @@ -30,7 +30,6 @@ import android.view.HapticFeedbackConstants import android.view.KeyEvent import android.view.LayoutInflater import android.view.Menu -import android.view.MenuInflater import android.view.MenuItem import android.view.View import android.view.ViewGroup @@ -1055,15 +1054,14 @@ class TimelineFragment @Inject constructor( } @SuppressLint("RestrictedApi") - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + override fun handlePostCreateMenu(menu: Menu) { if (isThreadTimeLine()) { if (menu is MenuBuilder) menu.setOptionalIconsVisible(true) } - super.onCreateOptionsMenu(menu, inflater) // We use a custom layout for this menu item, so we need to set a ClickListener menu.findItem(R.id.open_matrix_apps)?.let { menuItem -> menuItem.actionView.debouncedClicks { - onOptionsItemSelected(menuItem) + handleMenuItemSelected(menuItem) } } val joinConfItem = menu.findItem(R.id.join_conference) @@ -1073,13 +1071,13 @@ class TimelineFragment @Inject constructor( // Custom thread notification menu item menu.findItem(R.id.menu_timeline_thread_list)?.let { menuItem -> - menuItem.actionView.setOnClickListener { - onOptionsItemSelected(menuItem) + menuItem.actionView.debouncedClicks { + handleMenuItemSelected(menuItem) } } } - override fun onPrepareOptionsMenu(menu: Menu) { + override fun handlePrepareMenu(menu: Menu) { menu.forEach { it.isVisible = timelineViewModel.isMenuItemVisible(it.itemId) } @@ -1121,7 +1119,7 @@ class TimelineFragment @Inject constructor( } } - override fun onOptionsItemSelected(item: MenuItem): Boolean { + override fun handleMenuItemSelected(item: MenuItem): Boolean { return when (item.itemId) { R.id.invite -> { navigator.openInviteUsersToRoom(requireActivity(), timelineArgs.roomId) @@ -1174,7 +1172,7 @@ class TimelineFragment @Inject constructor( } true } - else -> super.onOptionsItemSelected(item) + else -> false } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/threads/list/views/ThreadListFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/threads/list/views/ThreadListFragment.kt index 13bf056301..7a4f8bb62d 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/threads/list/views/ThreadListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/threads/list/views/ThreadListFragment.kt @@ -19,7 +19,6 @@ package im.vector.app.features.home.room.threads.list.views import android.os.Bundle import android.view.LayoutInflater import android.view.Menu -import android.view.MenuInflater import android.view.MenuItem import android.view.View import android.view.ViewGroup @@ -71,27 +70,26 @@ class ThreadListFragment @Inject constructor( analyticsScreenName = MobileScreen.ScreenName.ThreadList } - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - super.onCreateOptionsMenu(menu, inflater) - + override fun handlePostCreateMenu(menu: Menu) { + // We use a custom layout for this menu item, so we need to set a ClickListener menu.findItem(R.id.menu_thread_list_filter)?.let { menuItem -> - menuItem.actionView.setOnClickListener { - onOptionsItemSelected(menuItem) + menuItem.actionView.debouncedClicks { + handleMenuItemSelected(menuItem) } } } - override fun onOptionsItemSelected(item: MenuItem): Boolean { + override fun handleMenuItemSelected(item: MenuItem): Boolean { return when (item.itemId) { R.id.menu_thread_list_filter -> { ThreadListBottomSheet().show(childFragmentManager, "Filtering") true } - else -> super.onOptionsItemSelected(item) + else -> false } } - override fun onPrepareOptionsMenu(menu: Menu) { + override fun handlePrepareMenu(menu: Menu) { withState(threadListViewModel) { state -> val filterIcon = menu.findItem(R.id.menu_thread_list_filter).actionView val filterBadge = filterIcon.findViewById(R.id.threadListFilterBadge) diff --git a/vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt b/vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt index 7fce09cad7..63f820f186 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationPreviewFragment.kt @@ -99,14 +99,14 @@ class LocationPreviewFragment @Inject constructor( override fun getMenuRes() = R.menu.menu_location_preview - override fun onOptionsItemSelected(item: MenuItem): Boolean { - when (item.itemId) { + override fun handleMenuItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { R.id.share_external -> { onShareLocationExternal() - return true + true } + else -> false } - return super.onOptionsItemSelected(item) } private fun onShareLocationExternal() { diff --git a/vector/src/main/java/im/vector/app/features/rageshake/BugReportActivity.kt b/vector/src/main/java/im/vector/app/features/rageshake/BugReportActivity.kt index c761c498d4..d78b9b21a5 100755 --- a/vector/src/main/java/im/vector/app/features/rageshake/BugReportActivity.kt +++ b/vector/src/main/java/im/vector/app/features/rageshake/BugReportActivity.kt @@ -120,29 +120,27 @@ class BugReportActivity : VectorBaseActivity() { override fun getMenuRes() = R.menu.bug_report - override fun onPrepareOptionsMenu(menu: Menu): Boolean { + override fun handlePrepareMenu(menu: Menu) { menu.findItem(R.id.ic_action_send_bug_report)?.let { val isValid = !views.bugReportMaskView.isVisible it.isEnabled = isValid it.icon.alpha = if (isValid) 255 else 100 } - - return super.onPrepareOptionsMenu(menu) } - override fun onOptionsItemSelected(item: MenuItem): Boolean { - when (item.itemId) { + override fun handleMenuItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { R.id.ic_action_send_bug_report -> { if (views.bugReportEditText.text.toString().trim().length >= 10) { sendBugReport() } else { views.bugReportTextInputLayout.error = getString(R.string.bug_report_error_too_short) } - return true + true } + else -> super.handleMenuItemSelected(item) } - return super.onOptionsItemSelected(item) } /** diff --git a/vector/src/main/java/im/vector/app/features/reactions/EmojiReactionPickerActivity.kt b/vector/src/main/java/im/vector/app/features/reactions/EmojiReactionPickerActivity.kt index f47b5b2411..4296a7a3b5 100644 --- a/vector/src/main/java/im/vector/app/features/reactions/EmojiReactionPickerActivity.kt +++ b/vector/src/main/java/im/vector/app/features/reactions/EmojiReactionPickerActivity.kt @@ -138,10 +138,7 @@ class EmojiReactionPickerActivity : VectorBaseActivity searchItem.setOnActionExpandListener(object : MenuItem.OnActionExpandListener { @@ -175,7 +172,6 @@ class EmojiReactionPickerActivity : VectorBaseActivity { sharedActionViewModel.post(RoomDirectorySharedAction.ChangeProtocol) true } - else -> - super.onOptionsItemSelected(item) + else -> false } } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt index b82da8aa55..8b7e450653 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt @@ -160,14 +160,14 @@ class RoomMemberProfileFragment @Inject constructor( } } - override fun onOptionsItemSelected(item: MenuItem): Boolean { - when (item.itemId) { + override fun handleMenuItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { R.id.roomMemberProfileShareAction -> { viewModel.handle(RoomMemberProfileAction.ShareRoomMemberProfile) - return true + true } + else -> false } - return super.onOptionsItemSelected(item) } private fun handleStartVerification(startVerification: RoomMemberProfileViewEvents.StartVerification) { diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt index 1b9912d2e0..07afe5485a 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt @@ -170,14 +170,14 @@ class RoomProfileFragment @Inject constructor( headerViews.roomProfileAliasView.copyOnLongClick() } - override fun onOptionsItemSelected(item: MenuItem): Boolean { - when (item.itemId) { + override fun handleMenuItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { R.id.roomProfileShareAction -> { roomProfileViewModel.handle(RoomProfileAction.ShareRoomProfile) - return true + true } + else -> false } - return super.onOptionsItemSelected(item) } private fun handleQuickActions(action: RoomListQuickActionsSharedAction) = when (action) { diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsFragment.kt index 4f92524efc..bcdc1a2202 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/settings/RoomSettingsFragment.kt @@ -139,18 +139,20 @@ class RoomSettingsFragment @Inject constructor( super.onDestroyView() } - override fun onPrepareOptionsMenu(menu: Menu) { + override fun handlePrepareMenu(menu: Menu) { withState(viewModel) { state -> menu.findItem(R.id.roomSettingsSaveAction).isVisible = state.showSaveAction } - super.onPrepareOptionsMenu(menu) } - override fun onOptionsItemSelected(item: MenuItem): Boolean { - if (item.itemId == R.id.roomSettingsSaveAction) { - viewModel.handle(RoomSettingsAction.Save) + override fun handleMenuItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.roomSettingsSaveAction -> { + viewModel.handle(RoomSettingsAction.Save) + true + } + else -> false } - return super.onOptionsItemSelected(item) } override fun invalidate() = withState(viewModel) { viewState -> diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestsFragment.kt index 4721fa7bfb..52778004e4 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestsFragment.kt @@ -26,8 +26,6 @@ import androidx.appcompat.app.AppCompatActivity import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.viewpager2.adapter.FragmentStateAdapter -import androidx.viewpager2.widget.ViewPager2 -import androidx.viewpager2.widget.ViewPager2.SCROLL_STATE_IDLE import com.airbnb.mvrx.Loading import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState @@ -61,19 +59,6 @@ class KeyRequestsFragment @Inject constructor( override fun getMenuRes(): Int = R.menu.menu_audit - private val pageAdapterListener = object : ViewPager2.OnPageChangeCallback() { - override fun onPageSelected(position: Int) { - invalidateOptionsMenu() - } - - override fun onPageScrollStateChanged(state: Int) { - childFragmentManager.fragments.forEach { - it.setHasOptionsMenu(state == SCROLL_STATE_IDLE) - } - invalidateOptionsMenu() - } - } - override fun invalidate() = withState(viewModel) { when (it.exporting) { is Loading -> views.exportWaitingView.isVisible = true @@ -81,16 +66,10 @@ class KeyRequestsFragment @Inject constructor( } } - override fun onDestroy() { - invalidateOptionsMenu() - super.onDestroy() - } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) mPagerAdapter = KeyReqPagerAdapter(this) views.devToolKeyRequestPager.adapter = mPagerAdapter - views.devToolKeyRequestPager.registerOnPageChangeCallback(pageAdapterListener) TabLayoutMediator(views.devToolKeyRequestTabs, views.devToolKeyRequestPager) { tab, position -> when (position) { @@ -119,25 +98,26 @@ class KeyRequestsFragment @Inject constructor( } override fun onDestroyView() { - views.devToolKeyRequestPager.unregisterOnPageChangeCallback(pageAdapterListener) mPagerAdapter = null super.onDestroyView() } - override fun onOptionsItemSelected(item: MenuItem): Boolean { - if (item.itemId == R.id.audit_export) { - selectTxtFileToWrite( - activity = requireActivity(), - activityResultLauncher = epxortAuditForActivityResult, - defaultFileName = "audit-export_${clock.epochMillis()}.txt", - chooserHint = "Export Audit" - ) - return true + override fun handleMenuItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.audit_export -> { + selectTxtFileToWrite( + activity = requireActivity(), + activityResultLauncher = exportAuditForActivityResult, + defaultFileName = "audit-export_${clock.epochMillis()}.txt", + chooserHint = "Export Audit" + ) + true + } + else -> false } - return super.onOptionsItemSelected(item) } - private val epxortAuditForActivityResult = registerStartForActivityResult { activityResult -> + private val exportAuditForActivityResult = registerStartForActivityResult { activityResult -> if (activityResult.resultCode == Activity.RESULT_OK) { val uri = activityResult.data?.data if (uri != null) { diff --git a/vector/src/main/java/im/vector/app/features/settings/push/PushGatewaysFragment.kt b/vector/src/main/java/im/vector/app/features/settings/push/PushGatewaysFragment.kt index 82462d7cc0..524a2a9fcc 100644 --- a/vector/src/main/java/im/vector/app/features/settings/push/PushGatewaysFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/push/PushGatewaysFragment.kt @@ -46,14 +46,13 @@ class PushGatewaysFragment @Inject constructor( override fun getMenuRes() = R.menu.menu_push_gateways - override fun onOptionsItemSelected(item: MenuItem): Boolean { + override fun handleMenuItemSelected(item: MenuItem): Boolean { return when (item.itemId) { R.id.refresh -> { viewModel.handle(PushGatewayAction.Refresh) true } - else -> - super.onOptionsItemSelected(item) + else -> false } } diff --git a/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryFragment.kt index 4cbbbc876d..671bfa48bb 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/explore/SpaceDirectoryFragment.kt @@ -177,40 +177,41 @@ class SpaceDirectoryFragment @Inject constructor( views.addOrCreateChatRoomButton.isVisible = state.canAddRooms } - override fun onPrepareOptionsMenu(menu: Menu) = withState(viewModel) { state -> - menu.findItem(R.id.spaceAddRoom)?.isVisible = state.canAddRooms - menu.findItem(R.id.spaceCreateRoom)?.isVisible = false // Not yet implemented + override fun handlePrepareMenu(menu: Menu) { + withState(viewModel) { state -> + menu.findItem(R.id.spaceAddRoom)?.isVisible = state.canAddRooms + menu.findItem(R.id.spaceCreateRoom)?.isVisible = false // Not yet implemented - menu.findItem(R.id.spaceSearch)?.let { searchItem -> - val searchView = searchItem.actionView as SearchView - searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { - override fun onQueryTextSubmit(query: String?): Boolean { - return true - } + menu.findItem(R.id.spaceSearch)?.let { searchItem -> + val searchView = searchItem.actionView as SearchView + searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { + override fun onQueryTextSubmit(query: String?): Boolean { + return true + } - override fun onQueryTextChange(newText: String?): Boolean { - onFilterQueryChanged(newText) - return true - } - }) + override fun onQueryTextChange(newText: String?): Boolean { + onFilterQueryChanged(newText) + return true + } + }) + } } - super.onPrepareOptionsMenu(menu) } - override fun onOptionsItemSelected(item: MenuItem): Boolean { - when (item.itemId) { + override fun handleMenuItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { R.id.spaceAddRoom -> { withState(viewModel) { state -> addExistingRooms(state.spaceId) } - return true + true } R.id.spaceCreateRoom -> { // not implemented yet - return true + true } + else -> false } - return super.onOptionsItemSelected(item) } override fun onFilterQueryChanged(query: String?) { diff --git a/vector/src/main/java/im/vector/app/features/spaces/leave/SpaceLeaveAdvancedFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/leave/SpaceLeaveAdvancedFragment.kt index 071dadb3b4..a01cfeb321 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/leave/SpaceLeaveAdvancedFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/leave/SpaceLeaveAdvancedFragment.kt @@ -89,7 +89,7 @@ class SpaceLeaveAdvancedFragment @Inject constructor( } } - override fun onPrepareOptionsMenu(menu: Menu) { + override fun handlePrepareMenu(menu: Menu) { menu.findItem(R.id.menu_space_leave_search)?.let { searchItem -> searchItem.bind( onExpanded = { viewModel.handle(SpaceLeaveAdvanceViewAction.SetFilteringEnabled(isEnabled = true)) }, @@ -97,7 +97,6 @@ class SpaceLeaveAdvancedFragment @Inject constructor( onTextChanged = { viewModel.handle(SpaceLeaveAdvanceViewAction.UpdateFilter(it)) } ) } - super.onPrepareOptionsMenu(menu) } override fun onDestroyView() { diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceAddRoomFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceAddRoomFragment.kt index 28d33bd1bf..3e1d500ddc 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceAddRoomFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceAddRoomFragment.kt @@ -151,17 +151,18 @@ class SpaceAddRoomFragment @Inject constructor( } } - override fun onPrepareOptionsMenu(menu: Menu) { - super.onPrepareOptionsMenu(menu) + override fun handlePrepareMenu(menu: Menu) { menu.findItem(R.id.spaceAddRoomSaveItem).isVisible = saveNeeded } - override fun onOptionsItemSelected(item: MenuItem): Boolean { - if (item.itemId == R.id.spaceAddRoomSaveItem) { - viewModel.handle(SpaceAddRoomActions.Save) - return true + override fun handleMenuItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.spaceAddRoomSaveItem -> { + viewModel.handle(SpaceAddRoomActions.Save) + true + } + else -> false } - return super.onOptionsItemSelected(item) } override fun onDestroyView() { diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsFragment.kt index b99fe0f025..51bd884908 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceSettingsFragment.kt @@ -111,18 +111,20 @@ class SpaceSettingsFragment @Inject constructor( super.onDestroyView() } - override fun onPrepareOptionsMenu(menu: Menu) { + override fun handlePrepareMenu(menu: Menu) { withState(viewModel) { state -> menu.findItem(R.id.roomSettingsSaveAction).isVisible = state.showSaveAction } - super.onPrepareOptionsMenu(menu) } - override fun onOptionsItemSelected(item: MenuItem): Boolean { - if (item.itemId == R.id.roomSettingsSaveAction) { - viewModel.handle(RoomSettingsAction.Save) + override fun handleMenuItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.roomSettingsSaveAction -> { + viewModel.handle(RoomSettingsAction.Save) + true + } + else -> false } - return super.onOptionsItemSelected(item) } private fun renderRoomSummary(state: RoomSettingsViewState) { diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragment.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragment.kt index e893fdf0f3..6886ea446b 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragment.kt @@ -113,19 +113,20 @@ class UserListFragment @Inject constructor( super.onDestroyView() } - override fun onPrepareOptionsMenu(menu: Menu) { + override fun handlePrepareMenu(menu: Menu) { withState(viewModel) { val showMenuItem = it.pendingSelections.isNotEmpty() menu.forEach { menuItem -> menuItem.isVisible = showMenuItem } } - super.onPrepareOptionsMenu(menu) } - override fun onOptionsItemSelected(item: MenuItem): Boolean = withState(viewModel) { - sharedActionViewModel.post(UserListSharedAction.OnMenuItemSelected(item.itemId, it.pendingSelections)) - return@withState true + override fun handleMenuItemSelected(item: MenuItem): Boolean { + withState(viewModel) { + sharedActionViewModel.post(UserListSharedAction.OnMenuItemSelected(item.itemId, it.pendingSelections)) + } + return true } private fun setupRecyclerView() { diff --git a/vector/src/main/java/im/vector/app/features/widgets/WidgetActivity.kt b/vector/src/main/java/im/vector/app/features/widgets/WidgetActivity.kt index 0c2df7856f..954f622801 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/WidgetActivity.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/WidgetActivity.kt @@ -64,8 +64,6 @@ class WidgetActivity : VectorBaseActivity() { override fun getBinding() = ActivityWidgetBinding.inflate(layoutInflater) - override fun getMenuRes() = R.menu.menu_widget - override fun getTitleRes() = R.string.room_widget_activity_title override fun initUiAndData() { diff --git a/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt b/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt index cbd4b8e1ee..cd77902a8c 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/WidgetFragment.kt @@ -79,7 +79,6 @@ class WidgetFragment @Inject constructor( override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - setHasOptionsMenu(true) views.widgetWebView.setupForWidget(this) if (fragmentArgs.kind.isAdmin()) { viewModel.getPostAPIMediator().setWebView(views.widgetWebView) @@ -136,53 +135,64 @@ class WidgetFragment @Inject constructor( } } - override fun onPrepareOptionsMenu(menu: Menu) = withState(viewModel) { state -> - val widget = state.asyncWidget() - menu.findItem(R.id.action_edit)?.isVisible = state.widgetKind != WidgetKind.INTEGRATION_MANAGER - if (widget == null) { - menu.findItem(R.id.action_refresh)?.isVisible = false - menu.findItem(R.id.action_widget_open_ext)?.isVisible = false - menu.findItem(R.id.action_delete)?.isVisible = false - menu.findItem(R.id.action_revoke)?.isVisible = false - } else { - menu.findItem(R.id.action_refresh)?.isVisible = true - menu.findItem(R.id.action_widget_open_ext)?.isVisible = true - menu.findItem(R.id.action_delete)?.isVisible = state.canManageWidgets && widget.isAddedByMe - menu.findItem(R.id.action_revoke)?.isVisible = state.status == WidgetStatus.WIDGET_ALLOWED && !widget.isAddedByMe + override fun getMenuRes() = R.menu.menu_widget + + override fun handlePrepareMenu(menu: Menu) { + withState(viewModel) { state -> + val widget = state.asyncWidget() + menu.findItem(R.id.action_edit)?.isVisible = state.widgetKind != WidgetKind.INTEGRATION_MANAGER + if (widget == null) { + menu.findItem(R.id.action_refresh)?.isVisible = false + menu.findItem(R.id.action_widget_open_ext)?.isVisible = false + menu.findItem(R.id.action_delete)?.isVisible = false + menu.findItem(R.id.action_revoke)?.isVisible = false + } else { + menu.findItem(R.id.action_refresh)?.isVisible = true + menu.findItem(R.id.action_widget_open_ext)?.isVisible = true + menu.findItem(R.id.action_delete)?.isVisible = state.canManageWidgets && widget.isAddedByMe + menu.findItem(R.id.action_revoke)?.isVisible = state.status == WidgetStatus.WIDGET_ALLOWED && !widget.isAddedByMe + } } - super.onPrepareOptionsMenu(menu) } - override fun onOptionsItemSelected(item: MenuItem): Boolean = withState(viewModel) { state -> - when (item.itemId) { - R.id.action_edit -> { - navigator.openIntegrationManager( - requireContext(), - integrationManagerActivityResultLauncher, - state.roomId, - state.widgetId, - state.widgetKind.screenId - ) - return@withState true - } - R.id.action_delete -> { - deleteWidget() - return@withState true - } - R.id.action_refresh -> if (state.formattedURL.complete) { - views.widgetWebView.reload() - return@withState true - } - R.id.action_widget_open_ext -> if (state.formattedURL.complete) { - openUrlInExternalBrowser(requireContext(), state.formattedURL.invoke()) - return@withState true - } - R.id.action_revoke -> if (state.status == WidgetStatus.WIDGET_ALLOWED) { - revokeWidget() - return@withState true + override fun handleMenuItemSelected(item: MenuItem): Boolean { + return withState(viewModel) { state -> + return@withState when (item.itemId) { + R.id.action_edit -> { + navigator.openIntegrationManager( + requireContext(), + integrationManagerActivityResultLauncher, + state.roomId, + state.widgetId, + state.widgetKind.screenId + ) + true + } + R.id.action_delete -> { + deleteWidget() + true + } + R.id.action_refresh -> { + if (state.formattedURL.complete) { + views.widgetWebView.reload() + } + true + } + R.id.action_widget_open_ext -> { + if (state.formattedURL.complete) { + openUrlInExternalBrowser(requireContext(), state.formattedURL.invoke()) + } + true + } + R.id.action_revoke -> { + if (state.status == WidgetStatus.WIDGET_ALLOWED) { + revokeWidget() + } + true + } + else -> false } } - return@withState super.onOptionsItemSelected(item) } override fun onBackPressed(toolbarButton: Boolean): Boolean = withState(viewModel) { state ->