From 62a20ba69d9c63c6c48ed8d3d2d5a3fd48a9e929 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Jun 2022 23:10:20 +0000 Subject: [PATCH 01/13] Bump activity from 1.4.0 to 1.5.0 Bumps activity from 1.4.0 to 1.5.0. --- updated-dependencies: - dependency-name: androidx.activity:activity dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index db9278b975..878d565f4d 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -50,7 +50,7 @@ ext.libs = [ ], androidx : [ 'annotation' : "androidx.annotation:annotation:1.4.0", - 'activity' : "androidx.activity:activity:1.4.0", + 'activity' : "androidx.activity:activity:1.5.0", 'annotations' : "androidx.annotation:annotation:1.3.0", 'appCompat' : "androidx.appcompat:appcompat:1.4.2", 'biometric' : "androidx.biometric:biometric:1.1.0", From 356718dc9a94a80f24df478b6a919c00eef3f914 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Jun 2022 23:11:02 +0000 Subject: [PATCH 02/13] Bump fragment from 1.4.1 to 1.5.0 Bumps `fragment` from 1.4.1 to 1.5.0. Updates `fragment-ktx` from 1.4.1 to 1.5.0 Updates `fragment-testing` from 1.4.1 to 1.5.0 --- updated-dependencies: - dependency-name: androidx.fragment:fragment-ktx dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: androidx.fragment:fragment-testing dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index db9278b975..0002cc9166 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -29,7 +29,7 @@ def bigImageViewer = "1.8.1" def jjwt = "0.11.5" def vanniktechEmoji = "0.15.0" -def fragment = "1.4.1" +def fragment = "1.5.0" // Testing def mockk = "1.12.3" // We need to use 1.12.3 to have mocking in androidTest until a new version is released: https://github.com/mockk/mockk/issues/819 From 1297ccd45c66a16c5ddcb60e0a3c29c20d192980 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 1 Jul 2022 11:58:01 +0200 Subject: [PATCH 03/13] Fix first compilation errors --- .../java/im/vector/app/core/platform/VectorBaseActivity.kt | 2 +- .../im/vector/app/features/devtools/RoomDevToolActivity.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) 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 571d2d38c0..66b613d292 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 @@ -417,7 +417,7 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver } } - override fun onMultiWindowModeChanged(isInMultiWindowMode: Boolean, newConfig: Configuration?) { + override fun onMultiWindowModeChanged(isInMultiWindowMode: Boolean, newConfig: Configuration) { super.onMultiWindowModeChanged(isInMultiWindowMode, newConfig) Timber.w("onMultiWindowModeChanged. isInMultiWindowMode: $isInMultiWindowMode") 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 6f661c5164..6225741310 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 @@ -174,8 +174,8 @@ class RoomDevToolActivity : SimpleFragmentActivity(), FragmentManager.OnBackStac super.onDestroy() } - override fun onPrepareOptionsMenu(menu: Menu?): Boolean = withState(viewModel) { state -> - menu?.forEach { + 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 From aae6e20f9c2eaf8b36ee95252e44f317fcd1a07c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 1 Jul 2022 17:05:32 +0200 Subject: [PATCH 04/13] Migration to activity 1.5.0. Rework menu management --- library/ui-styles/build.gradle | 1 + .../debug/DebugMaterialThemeActivity.kt | 31 +++++- tools/check/forbidden_strings_in_code.txt | 5 + .../app/core/platform/VectorBaseActivity.kt | 63 ++++++++---- .../app/core/platform/VectorBaseFragment.kt | 44 +++++++-- .../preview/AttachmentsPreviewFragment.kt | 10 +- .../app/features/call/VectorCallActivity.kt | 21 ++-- .../setup/KeysBackupSetupActivity.kt | 10 -- .../features/devtools/RoomDevToolActivity.kt | 45 +++++---- .../vector/app/features/home/HomeActivity.kt | 22 ++--- .../app/features/home/HomeDetailFragment.kt | 12 +-- .../home/room/detail/TimelineFragment.kt | 16 ++-- .../threads/list/views/ThreadListFragment.kt | 16 ++-- .../location/LocationPreviewFragment.kt | 8 +- .../features/rageshake/BugReportActivity.kt | 12 +-- .../reactions/EmojiReactionPickerActivity.kt | 6 +- .../roomdirectory/PublicRoomsFragment.kt | 5 +- .../RoomMemberProfileFragment.kt | 8 +- .../roomprofile/RoomProfileFragment.kt | 8 +- .../settings/RoomSettingsFragment.kt | 14 +-- .../settings/devtools/KeyRequestsFragment.kt | 46 +++------ .../settings/push/PushGatewaysFragment.kt | 5 +- .../spaces/explore/SpaceDirectoryFragment.kt | 41 ++++---- .../leave/SpaceLeaveAdvancedFragment.kt | 3 +- .../spaces/manage/SpaceAddRoomFragment.kt | 15 +-- .../spaces/manage/SpaceSettingsFragment.kt | 14 +-- .../userdirectory/UserListFragment.kt | 11 ++- .../app/features/widgets/WidgetActivity.kt | 2 - .../app/features/widgets/WidgetFragment.kt | 96 ++++++++++--------- 29 files changed, 320 insertions(+), 270 deletions(-) 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 -> From 944b447d938b117bc422feaec38f59dd60af046f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 1 Jul 2022 16:42:44 +0200 Subject: [PATCH 05/13] Fix regression when closing the screen to create a DM from the toolbar. Rework this part a bit. --- .../call/transfer/CallTransferPagerAdapter.kt | 1 + .../createdirect/CreateDirectRoomActivity.kt | 11 +++++------ .../invite/InviteUsersToRoomActivity.kt | 9 ++++----- .../features/userdirectory/UserListFragment.kt | 17 ++++++++++------- .../userdirectory/UserListFragmentArgs.kt | 1 + .../userdirectory/UserListSharedAction.kt | 2 +- 6 files changed, 22 insertions(+), 19 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferPagerAdapter.kt b/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferPagerAdapter.kt index 2bb544bdbb..3ec8f61978 100644 --- a/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferPagerAdapter.kt +++ b/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferPagerAdapter.kt @@ -49,6 +49,7 @@ class CallTransferPagerAdapter( fragment.arguments = UserListFragmentArgs( title = "", menuResId = -1, + submitMenuItemId = -1, singleSelection = true, showInviteActions = false, showToolbar = false, diff --git a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt index 6292217b67..12cd4ddab8 100644 --- a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt +++ b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt @@ -81,7 +81,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { when (action) { UserListSharedAction.Close -> finish() UserListSharedAction.GoBack -> onBackPressed() - is UserListSharedAction.OnMenuItemSelected -> onMenuItemSelected(action) + is UserListSharedAction.OnMenuItemSubmitClick -> handleOnMenuItemSubmitClick(action) UserListSharedAction.OpenPhoneBook -> openPhoneBook() UserListSharedAction.AddByQrCode -> openAddByQrCode() } @@ -93,7 +93,8 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { UserListFragment::class.java, UserListFragmentArgs( title = getString(R.string.fab_menu_create_chat), - menuResId = R.menu.vector_create_direct_room + menuResId = R.menu.vector_create_direct_room, + submitMenuItemId = R.id.action_create_direct_room, ) ) } @@ -159,10 +160,8 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() { } } - private fun onMenuItemSelected(action: UserListSharedAction.OnMenuItemSelected) { - if (action.itemId == R.id.action_create_direct_room) { - viewModel.handle(CreateDirectRoomAction.CreateRoomAndInviteSelectedUsers(action.selections)) - } + private fun handleOnMenuItemSubmitClick(action: UserListSharedAction.OnMenuItemSubmitClick) { + viewModel.handle(CreateDirectRoomAction.CreateRoomAndInviteSelectedUsers(action.selections)) } private fun renderCreateAndInviteState(state: Async) { diff --git a/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomActivity.kt b/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomActivity.kt index 304ec72ce2..883c879e90 100644 --- a/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomActivity.kt +++ b/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomActivity.kt @@ -71,7 +71,7 @@ class InviteUsersToRoomActivity : SimpleFragmentActivity() { when (sharedAction) { UserListSharedAction.Close -> finish() UserListSharedAction.GoBack -> onBackPressed() - is UserListSharedAction.OnMenuItemSelected -> onMenuItemSelected(sharedAction) + is UserListSharedAction.OnMenuItemSubmitClick -> handleOnMenuItemSubmitClick(sharedAction) UserListSharedAction.OpenPhoneBook -> openPhoneBook() // not exhaustive because it's a sharedAction else -> Unit @@ -85,6 +85,7 @@ class InviteUsersToRoomActivity : SimpleFragmentActivity() { UserListFragmentArgs( title = getString(R.string.invite_users_to_room_title), menuResId = R.menu.vector_invite_users_to_room, + submitMenuItemId = R.id.action_invite_users_to_room_invite, excludedUserIds = viewModel.getUserIdsOfRoomMembers(), showInviteActions = false ) @@ -94,10 +95,8 @@ class InviteUsersToRoomActivity : SimpleFragmentActivity() { viewModel.observeViewEvents { renderInviteEvents(it) } } - private fun onMenuItemSelected(action: UserListSharedAction.OnMenuItemSelected) { - if (action.itemId == R.id.action_invite_users_to_room_invite) { - viewModel.handle(InviteUsersToRoomAction.InviteSelectedUsers(action.selections)) - } + private fun handleOnMenuItemSubmitClick(action: UserListSharedAction.OnMenuItemSubmitClick) { + viewModel.handle(InviteUsersToRoomAction.InviteSelectedUsers(action.selections)) } private fun openPhoneBook() { 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 6886ea446b..9790750368 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 @@ -23,7 +23,6 @@ import android.view.MenuItem import android.view.View import android.view.ViewGroup import android.widget.ScrollView -import androidx.core.view.forEach import androidx.core.view.isVisible import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.activityViewModel @@ -114,19 +113,23 @@ class UserListFragment @Inject constructor( } override fun handlePrepareMenu(menu: Menu) { + if (args.submitMenuItemId == -1) return withState(viewModel) { val showMenuItem = it.pendingSelections.isNotEmpty() - menu.forEach { menuItem -> - menuItem.isVisible = showMenuItem - } + menu.findItem(args.submitMenuItemId).isVisible = showMenuItem } } override fun handleMenuItemSelected(item: MenuItem): Boolean { - withState(viewModel) { - sharedActionViewModel.post(UserListSharedAction.OnMenuItemSelected(item.itemId, it.pendingSelections)) + return when (item.itemId) { + args.submitMenuItemId -> { + withState(viewModel) { + sharedActionViewModel.post(UserListSharedAction.OnMenuItemSubmitClick(it.pendingSelections)) + } + true + } + else -> false } - return true } private fun setupRecyclerView() { diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragmentArgs.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragmentArgs.kt index 795d45272c..d6e55c29ae 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragmentArgs.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListFragmentArgs.kt @@ -23,6 +23,7 @@ import kotlinx.parcelize.Parcelize data class UserListFragmentArgs( val title: String, val menuResId: Int, + val submitMenuItemId: Int, val excludedUserIds: Set? = null, val singleSelection: Boolean = false, val showInviteActions: Boolean = true, diff --git a/vector/src/main/java/im/vector/app/features/userdirectory/UserListSharedAction.kt b/vector/src/main/java/im/vector/app/features/userdirectory/UserListSharedAction.kt index fca771793b..fb63b05e2f 100644 --- a/vector/src/main/java/im/vector/app/features/userdirectory/UserListSharedAction.kt +++ b/vector/src/main/java/im/vector/app/features/userdirectory/UserListSharedAction.kt @@ -21,7 +21,7 @@ import im.vector.app.core.platform.VectorSharedAction sealed class UserListSharedAction : VectorSharedAction { object Close : UserListSharedAction() object GoBack : UserListSharedAction() - data class OnMenuItemSelected(val itemId: Int, val selections: Set) : UserListSharedAction() + data class OnMenuItemSubmitClick(val selections: Set) : UserListSharedAction() object OpenPhoneBook : UserListSharedAction() object AddByQrCode : UserListSharedAction() } From 397614121c83578fa527c2f3c1b8681d5a6d2b84 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 1 Jul 2022 17:02:28 +0200 Subject: [PATCH 06/13] Fix warning on `onPictureInPictureModeChanged` method overriding. --- .../vector/app/features/call/VectorCallActivity.kt | 11 ++++++++--- .../features/call/conference/VectorJitsiActivity.kt | 13 ++++++------- .../reactions/EmojiReactionPickerActivity.kt | 1 - 3 files changed, 14 insertions(+), 11 deletions(-) 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 aefde07214..348983d431 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 @@ -22,7 +22,6 @@ import android.app.PictureInPictureParams import android.content.Context import android.content.Intent import android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP -import android.content.res.Configuration import android.graphics.Color import android.media.projection.MediaProjection import android.media.projection.MediaProjectionManager @@ -35,8 +34,10 @@ import android.view.View import android.view.WindowManager import androidx.activity.result.ActivityResult import androidx.annotation.StringRes +import androidx.core.app.PictureInPictureModeChangedInfo import androidx.core.content.ContextCompat import androidx.core.content.getSystemService +import androidx.core.util.Consumer import androidx.core.view.isInvisible import androidx.core.view.isVisible import com.airbnb.mvrx.Fail @@ -128,6 +129,7 @@ class VectorCallActivity : VectorBaseActivity(), CallContro window.statusBarColor = Color.TRANSPARENT window.navigationBarColor = Color.BLACK super.onCreate(savedInstanceState) + addOnPictureInPictureModeChangedListener(pictureInPictureModeChangedInfoConsumer) Timber.tag(loggerTag.value).v("EXTRA_MODE is ${intent.getStringExtra(EXTRA_MODE)}") if (intent.getStringExtra(EXTRA_MODE) == INCOMING_RINGING) { @@ -210,8 +212,10 @@ class VectorCallActivity : VectorBaseActivity(), CallContro return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && isInPictureInPictureMode } - override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean, newConfig: Configuration) = withState(callViewModel) { - renderState(it) + private val pictureInPictureModeChangedInfoConsumer = Consumer { + withState(callViewModel) { + renderState(it) + } } override fun handleMenuItemSelected(item: MenuItem): Boolean { @@ -232,6 +236,7 @@ class VectorCallActivity : VectorBaseActivity(), CallContro override fun onDestroy() { detachRenderersIfNeeded() turnScreenOffAndKeyguardOn() + removeOnPictureInPictureModeChangedListener(pictureInPictureModeChangedInfoConsumer) super.onDestroy() } diff --git a/vector/src/main/java/im/vector/app/features/call/conference/VectorJitsiActivity.kt b/vector/src/main/java/im/vector/app/features/call/conference/VectorJitsiActivity.kt index 86136eab15..5bf05d353c 100644 --- a/vector/src/main/java/im/vector/app/features/call/conference/VectorJitsiActivity.kt +++ b/vector/src/main/java/im/vector/app/features/call/conference/VectorJitsiActivity.kt @@ -19,12 +19,13 @@ package im.vector.app.features.call.conference import android.content.Context import android.content.Intent import android.content.pm.PackageManager -import android.content.res.Configuration import android.os.Build import android.os.Bundle import android.os.Parcelable import android.widget.FrameLayout import android.widget.Toast +import androidx.core.app.PictureInPictureModeChangedInfo +import androidx.core.util.Consumer import androidx.core.view.isVisible import androidx.lifecycle.Lifecycle import com.airbnb.mvrx.Fail @@ -66,6 +67,7 @@ class VectorJitsiActivity : VectorBaseActivity(), JitsiMee override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + addOnPictureInPictureModeChangedListener(pictureInPictureModeChangedInfoConsumer) jitsiViewModel.onEach { renderState(it) @@ -109,6 +111,7 @@ class VectorJitsiActivity : VectorBaseActivity(), JitsiMee ConferenceEventEmitter(this).emitConferenceEnded() } JitsiMeetActivityDelegate.onHostDestroy(this) + removeOnPictureInPictureModeChangedListener(pictureInPictureModeChangedInfoConsumer) super.onDestroy() } @@ -138,13 +141,9 @@ class VectorJitsiActivity : VectorBaseActivity(), JitsiMee .show() } - override fun onPictureInPictureModeChanged( - isInPictureInPictureMode: Boolean, - newConfig: Configuration - ) { - super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig) + private val pictureInPictureModeChangedInfoConsumer = Consumer { checkIfActivityShouldBeFinished() - Timber.w("onPictureInPictureModeChanged($isInPictureInPictureMode)") + Timber.w("onPictureInPictureModeChanged(${it.isInPictureInPictureMode})") } private fun checkIfActivityShouldBeFinished() { 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 4296a7a3b5..6a7914b6b5 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 @@ -21,7 +21,6 @@ import android.content.Intent import android.graphics.Typeface import android.util.TypedValue import android.view.Menu -import android.view.MenuInflater import android.view.MenuItem import android.widget.SearchView import androidx.core.view.isVisible From f7a0615105bcfe876bd5f9b0c9543f3232c58b02 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 1 Jul 2022 17:35:01 +0200 Subject: [PATCH 07/13] Fix warning on `onMultiWindowModeChanged` method overriding. --- .../vector/app/core/platform/VectorBaseActivity.kt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) 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 825b94fd5d..66081120cc 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 @@ -19,7 +19,6 @@ package im.vector.app.core.platform import android.annotation.SuppressLint import android.app.Activity import android.content.Context -import android.content.res.Configuration import android.os.Build import android.os.Bundle import android.os.Parcelable @@ -36,7 +35,9 @@ import androidx.annotation.MenuRes import androidx.annotation.StringRes import androidx.appcompat.app.AppCompatActivity import androidx.coordinatorlayout.widget.CoordinatorLayout +import androidx.core.app.MultiWindowModeChangedInfo import androidx.core.content.ContextCompat +import androidx.core.util.Consumer import androidx.core.view.MenuProvider import androidx.core.view.isVisible import androidx.fragment.app.Fragment @@ -202,6 +203,7 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver supportFragmentManager.fragmentFactory = fragmentFactory viewModelFactory = activityEntryPoint.viewModelFactory() super.onCreate(savedInstanceState) + addOnMultiWindowModeChangedListener(onMultiWindowModeChangedListener) setupMenu() configurationViewModel = viewModelProvider.get(ConfigurationViewModel::class.java) bugReporter = singletonEntryPoint.bugReporter() @@ -360,6 +362,7 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver } override fun onDestroy() { + removeOnMultiWindowModeChangedListener(onMultiWindowModeChangedListener) super.onDestroy() Timber.i("onDestroy Activity ${javaClass.simpleName}") } @@ -445,11 +448,9 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver } } - override fun onMultiWindowModeChanged(isInMultiWindowMode: Boolean, newConfig: Configuration) { - super.onMultiWindowModeChanged(isInMultiWindowMode, newConfig) - - Timber.w("onMultiWindowModeChanged. isInMultiWindowMode: $isInMultiWindowMode") - bugReporter.inMultiWindowMode = isInMultiWindowMode + private val onMultiWindowModeChangedListener = Consumer { + Timber.w("onMultiWindowModeChanged. isInMultiWindowMode: ${it.isInMultiWindowMode}") + bugReporter.inMultiWindowMode = it.isInMultiWindowMode } protected fun createFragment(fragmentClass: Class, argsParcelable: Parcelable? = null): Fragment { From be099dcae028dd1befcb725a4c933e95c9c52206 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 4 Jul 2022 17:10:12 +0200 Subject: [PATCH 08/13] Menu: extract management to a common interface / Migrate Activities --- .../app/core/platform/VectorBaseActivity.kt | 32 +++++----------- .../app/core/platform/VectorMenuProvider.kt | 37 +++++++++++++++++++ .../app/features/call/VectorCallActivity.kt | 8 +++- .../features/devtools/RoomDevToolActivity.kt | 8 +++- .../vector/app/features/home/HomeActivity.kt | 6 ++- .../features/rageshake/BugReportActivity.kt | 7 +++- .../reactions/EmojiReactionPickerActivity.kt | 9 ++++- 7 files changed, 75 insertions(+), 32 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/core/platform/VectorMenuProvider.kt 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 66081120cc..9bad0f8e90 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 @@ -31,7 +31,6 @@ import android.view.WindowManager import android.widget.TextView import androidx.annotation.CallSuper import androidx.annotation.MainThread -import androidx.annotation.MenuRes import androidx.annotation.StringRes import androidx.appcompat.app.AppCompatActivity import androidx.coordinatorlayout.widget.CoordinatorLayout @@ -90,6 +89,7 @@ import im.vector.app.features.themes.ThemeUtils import im.vector.app.receivers.DebugReceiver import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.failure.GlobalError import org.matrix.android.sdk.api.failure.InitialSyncRequestReason @@ -257,21 +257,23 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver private fun setupMenu() { // Always add a MenuProvider to handle the back action from the Toolbar + val vectorMenuProvider = this as? VectorMenuProvider addMenuProvider( object : MenuProvider { override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) { - getMenuRes() - .takeIf { it != -1 } - ?.let { menuInflater.inflate(it, menu) } - handlePostCreateMenu(menu) + vectorMenuProvider?.let { + menuInflater.inflate(it.getMenuRes(), menu) + it.handlePostCreateMenu(menu) + } } override fun onPrepareMenu(menu: Menu) { - handlePrepareMenu(menu) + vectorMenuProvider?.handlePrepareMenu(menu) } override fun onMenuItemSelected(menuItem: MenuItem): Boolean { - return handleMenuItemSelected(menuItem) + return vectorMenuProvider?.handleMenuItemSelected(menuItem).orFalse() || + handleMenuItemHome(menuItem) } }, this, @@ -492,21 +494,7 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver } } - /* ========================================================================================== - * MENU MANAGEMENT - * ========================================================================================== */ - - @MenuRes - open fun getMenuRes() = -1 - - // 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 { + private fun handleMenuItemHome(item: MenuItem): Boolean { return when (item.itemId) { android.R.id.home -> { onBackPressed(true) diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorMenuProvider.kt b/vector/src/main/java/im/vector/app/core/platform/VectorMenuProvider.kt new file mode 100644 index 0000000000..c94a2fcdb0 --- /dev/null +++ b/vector/src/main/java/im/vector/app/core/platform/VectorMenuProvider.kt @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.core.platform + +import android.view.Menu +import android.view.MenuItem +import androidx.annotation.MenuRes + +/** + * Let your Activity of Fragment implement this interface if they provide a Menu + */ +interface VectorMenuProvider { + @MenuRes + fun getMenuRes(): Int + + // No op by default + fun handlePostCreateMenu(menu: Menu) = Unit + + // No op by default + fun handlePrepareMenu(menu: Menu) = Unit + + fun handleMenuItemSelected(item: MenuItem): Boolean +} 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 348983d431..2384e560ee 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 @@ -51,6 +51,7 @@ import im.vector.app.R import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.extensions.setTextOrHide import im.vector.app.core.platform.VectorBaseActivity +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.utils.PERMISSIONS_FOR_AUDIO_IP_CALL import im.vector.app.core.utils.PERMISSIONS_FOR_VIDEO_IP_CALL import im.vector.app.core.utils.checkPermissions @@ -95,7 +96,10 @@ data class CallArgs( private val loggerTag = LoggerTag("VectorCallActivity", LoggerTag.VOIP) @AndroidEntryPoint -class VectorCallActivity : VectorBaseActivity(), CallControlsView.InteractionListener { +class VectorCallActivity : + VectorBaseActivity(), + CallControlsView.InteractionListener, + VectorMenuProvider { override fun getBinding() = ActivityCallBinding.inflate(layoutInflater) @@ -229,7 +233,7 @@ class VectorCallActivity : VectorBaseActivity(), CallContro onBackPressed() true } - else -> super.handleMenuItemSelected(item) + else -> false } } 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 88499c7531..e848d0631f 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 @@ -36,6 +36,7 @@ import dagger.hilt.android.AndroidEntryPoint import im.vector.app.R import im.vector.app.core.extensions.replaceFragment import im.vector.app.core.platform.SimpleFragmentActivity +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.resources.ColorProvider import im.vector.app.core.utils.createJSonViewerStyleProvider import kotlinx.parcelize.Parcelize @@ -43,7 +44,10 @@ import org.billcarsonfr.jsonviewer.JSonViewerFragment import javax.inject.Inject @AndroidEntryPoint -class RoomDevToolActivity : SimpleFragmentActivity(), FragmentManager.OnBackStackChangedListener { +class RoomDevToolActivity : + SimpleFragmentActivity(), + FragmentManager.OnBackStackChangedListener, + VectorMenuProvider { @Inject lateinit var colorProvider: ColorProvider @@ -143,7 +147,7 @@ class RoomDevToolActivity : SimpleFragmentActivity(), FragmentManager.OnBackStac viewModel.handle(RoomDevToolAction.MenuItemSend) true } - else -> super.handleMenuItemSelected(item) + else -> false } } 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 82c9c78852..1c66cdda64 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 @@ -43,6 +43,7 @@ import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.extensions.replaceFragment import im.vector.app.core.extensions.validateBackPressed import im.vector.app.core.platform.VectorBaseActivity +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.pushers.PushersManager import im.vector.app.core.pushers.UnifiedPushHelper import im.vector.app.databinding.ActivityHomeBinding @@ -103,7 +104,8 @@ class HomeActivity : VectorBaseActivity(), NavigationInterceptor, SpaceInviteBottomSheet.InteractionListener, - MatrixToBottomSheet.InteractionListener { + MatrixToBottomSheet.InteractionListener, + VectorMenuProvider { private lateinit var sharedActionViewModel: HomeSharedActionViewModel @@ -584,7 +586,7 @@ class HomeActivity : navigator.openSettings(this) true } - else -> super.handleMenuItemSelected(item) + else -> false } } 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 d78b9b21a5..c7f549c5cb 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 @@ -28,6 +28,7 @@ import com.airbnb.mvrx.withState import dagger.hilt.android.AndroidEntryPoint import im.vector.app.R import im.vector.app.core.platform.VectorBaseActivity +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.databinding.ActivityBugReportBinding import org.matrix.android.sdk.api.extensions.tryOrNull import timber.log.Timber @@ -36,7 +37,9 @@ import timber.log.Timber * Form to send a bug report. */ @AndroidEntryPoint -class BugReportActivity : VectorBaseActivity() { +class BugReportActivity : + VectorBaseActivity(), + VectorMenuProvider { override fun getBinding() = ActivityBugReportBinding.inflate(layoutInflater) @@ -139,7 +142,7 @@ class BugReportActivity : VectorBaseActivity() { } true } - else -> super.handleMenuItemSelected(item) + else -> false } } 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 6a7914b6b5..f9be57b13f 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 @@ -32,6 +32,7 @@ import im.vector.app.EmojiCompatFontProvider import im.vector.app.R import im.vector.app.core.extensions.observeEvent import im.vector.app.core.platform.VectorBaseActivity +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.databinding.ActivityEmojiReactionPickerBinding import im.vector.app.features.reactions.data.EmojiDataSource import im.vector.lib.core.utils.flow.throttleFirst @@ -47,13 +48,17 @@ import javax.inject.Inject * TODO Finish Refactor to vector base activity */ @AndroidEntryPoint -class EmojiReactionPickerActivity : VectorBaseActivity(), - EmojiCompatFontProvider.FontProviderListener { +class EmojiReactionPickerActivity : + VectorBaseActivity(), + EmojiCompatFontProvider.FontProviderListener, + VectorMenuProvider { lateinit var viewModel: EmojiChooserViewModel override fun getMenuRes() = R.menu.menu_emoji_reaction_picker + override fun handleMenuItemSelected(item: MenuItem) = false + override fun getBinding() = ActivityEmojiReactionPickerBinding.inflate(layoutInflater) override fun getCoordinatorLayout() = views.coordinatorLayout From 81505d3802a06d3bcee0e36c6ff5ba25fbab42e5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 4 Jul 2022 17:28:18 +0200 Subject: [PATCH 09/13] Menu: extract management to a common interface / Migrate Fragments --- .../app/core/platform/VectorBaseFragment.kt | 17 +++-------------- .../preview/AttachmentsPreviewFragment.kt | 5 ++++- .../app/features/home/HomeDetailFragment.kt | 4 +++- .../home/room/detail/TimelineFragment.kt | 4 +++- .../threads/list/views/ThreadListFragment.kt | 4 +++- .../location/LocationPreviewFragment.kt | 4 +++- .../roomdirectory/PublicRoomsFragment.kt | 4 +++- .../RoomMemberProfileFragment.kt | 4 +++- .../features/roomprofile/RoomProfileFragment.kt | 4 +++- .../settings/RoomSettingsFragment.kt | 4 +++- .../settings/devtools/KeyRequestsFragment.kt | 4 +++- .../settings/push/PushGatewaysFragment.kt | 4 +++- .../spaces/explore/SpaceDirectoryFragment.kt | 4 +++- .../spaces/leave/SpaceLeaveAdvancedFragment.kt | 6 +++++- .../spaces/manage/SpaceAddRoomFragment.kt | 5 ++++- .../spaces/manage/SpaceSettingsFragment.kt | 4 +++- .../features/userdirectory/UserListFragment.kt | 4 +++- .../app/features/widgets/WidgetFragment.kt | 4 +++- 18 files changed, 58 insertions(+), 31 deletions(-) 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 a1fd774757..340c906a6d 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 @@ -164,12 +164,13 @@ abstract class VectorBaseFragment : Fragment(), MavericksView } private fun setupMenu() { - val menuRes = getMenuRes().takeIf { it != -1 } ?: return + if (this !is VectorMenuProvider) return + if (getMenuRes() == -1) return val menuHost: MenuHost = requireActivity() menuHost.addMenuProvider( object : MenuProvider { override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) { - menuInflater.inflate(menuRes, menu) + menuInflater.inflate(getMenuRes(), menu) handlePostCreateMenu(menu) } @@ -296,18 +297,6 @@ abstract class VectorBaseFragment : Fragment(), MavericksView * MENU MANAGEMENT * ========================================================================================== */ - open fun getMenuRes() = -1 - - // No op by default - open fun handlePostCreateMenu(menu: Menu) = Unit - - // 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 protected fun invalidateOptionsMenu() = requireActivity().invalidateOptionsMenu() 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 5a4905942b..c3a4ae7df2 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 @@ -44,6 +44,7 @@ import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.insertBeforeLast import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.resources.ColorProvider import im.vector.app.core.time.Clock import im.vector.app.core.utils.OnSnapPositionChangeListener @@ -67,7 +68,9 @@ class AttachmentsPreviewFragment @Inject constructor( private val attachmentBigPreviewController: AttachmentBigPreviewController, private val colorProvider: ColorProvider, private val clock: Clock, -) : VectorBaseFragment(), AttachmentMiniaturePreviewController.Callback { +) : VectorBaseFragment(), + AttachmentMiniaturePreviewController.Callback, + VectorMenuProvider { private val fragmentArgs: AttachmentsPreviewArgs by args() private val viewModel: AttachmentsPreviewViewModel by fragmentViewModel() 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 787c39b3e3..a3bc5144d1 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 @@ -36,6 +36,7 @@ import im.vector.app.core.extensions.toMvRxBundle import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.resources.ColorProvider import im.vector.app.core.ui.views.CurrentCallsView import im.vector.app.core.ui.views.CurrentCallsViewPresenter @@ -71,7 +72,8 @@ class HomeDetailFragment @Inject constructor( ) : VectorBaseFragment(), KeysBackupBanner.Delegate, CurrentCallsView.Callback, - OnBackPressed { + OnBackPressed, + VectorMenuProvider { private val viewModel: HomeDetailViewModel by fragmentViewModel() private val unknownDeviceDetectorSharedViewModel: UnknownDeviceDetectorSharedViewModel by activityViewModel() 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 8e2e5468a8..b821cadcc0 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 @@ -88,6 +88,7 @@ import im.vector.app.core.hardware.vibrate import im.vector.app.core.intent.getFilenameFromUri import im.vector.app.core.intent.getMimeTypeFromUri import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.platform.lifecycleAwareLazy import im.vector.app.core.platform.showOptimizedSnackbar import im.vector.app.core.resources.ColorProvider @@ -279,7 +280,8 @@ class TimelineFragment @Inject constructor( AttachmentTypeSelectorView.Callback, AttachmentsHelper.Callback, GalleryOrCameraDialogHelper.Listener, - CurrentCallsView.Callback { + CurrentCallsView.Callback, + VectorMenuProvider { companion object { 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 7a4f8bb62d..aaa9846c39 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 @@ -30,6 +30,7 @@ import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.databinding.FragmentThreadListBinding import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.home.AvatarRenderer @@ -53,7 +54,8 @@ class ThreadListFragment @Inject constructor( private val threadListController: ThreadListController, val threadListViewModelFactory: ThreadListViewModel.Factory ) : VectorBaseFragment(), - ThreadListController.Listener { + ThreadListController.Listener, + VectorMenuProvider { private val threadListViewModel: ThreadListViewModel by fragmentViewModel() 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 63f820f186..131119a7aa 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 @@ -26,6 +26,7 @@ import com.airbnb.mvrx.args import com.mapbox.mapboxsdk.maps.MapView import im.vector.app.R import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.utils.openLocation import im.vector.app.databinding.FragmentLocationPreviewBinding import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider @@ -38,7 +39,8 @@ import javax.inject.Inject class LocationPreviewFragment @Inject constructor( private val urlMapProvider: UrlMapProvider, private val locationPinProvider: LocationPinProvider -) : VectorBaseFragment() { +) : VectorBaseFragment(), + VectorMenuProvider { private val args: LocationSharingArgs by args() diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomsFragment.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomsFragment.kt index c9a96f703c..e16e1ec313 100644 --- a/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomsFragment.kt @@ -30,6 +30,7 @@ import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.trackItemsVisibilityChange import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.platform.showOptimizedSnackbar import im.vector.app.core.utils.toast import im.vector.app.databinding.FragmentPublicRoomsBinding @@ -55,7 +56,8 @@ class PublicRoomsFragment @Inject constructor( private val permalinkHandler: PermalinkHandler, private val session: Session ) : VectorBaseFragment(), - PublicRoomsController.Callback { + PublicRoomsController.Callback, + VectorMenuProvider { private val viewModel: RoomDirectoryViewModel by activityViewModel() private lateinit var sharedActionViewModel: RoomDirectorySharedActionViewModel 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 8b7e450653..88a27f246c 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 @@ -42,6 +42,7 @@ import im.vector.app.core.extensions.copyOnLongClick import im.vector.app.core.extensions.setTextOrHide import im.vector.app.core.platform.StateView import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.utils.startSharePlainTextIntent import im.vector.app.databinding.DialogBaseEditTextBinding import im.vector.app.databinding.DialogShareQrCodeBinding @@ -74,7 +75,8 @@ class RoomMemberProfileFragment @Inject constructor( private val roomDetailPendingActionStore: RoomDetailPendingActionStore, private val matrixItemColorProvider: MatrixItemColorProvider ) : VectorBaseFragment(), - RoomMemberProfileController.Callback { + RoomMemberProfileController.Callback, + VectorMenuProvider { private lateinit var headerViews: ViewStubRoomMemberProfileHeaderBinding 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 07afe5485a..2f8128b7af 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 @@ -39,6 +39,7 @@ import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.copyOnLongClick import im.vector.app.core.extensions.setTextOrHide import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.utils.copyToClipboard import im.vector.app.core.utils.startSharePlainTextIntent import im.vector.app.databinding.FragmentMatrixProfileBinding @@ -70,7 +71,8 @@ class RoomProfileFragment @Inject constructor( private val roomDetailPendingActionStore: RoomDetailPendingActionStore, ) : VectorBaseFragment(), - RoomProfileController.Callback { + RoomProfileController.Callback, + VectorMenuProvider { private lateinit var headerViews: ViewStubRoomProfileHeaderBinding 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 bcdc1a2202..45c8461fa7 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 @@ -36,6 +36,7 @@ import im.vector.app.core.extensions.configureWith import im.vector.app.core.intent.getFilenameFromUri import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.resources.ColorProvider import im.vector.app.core.time.Clock import im.vector.app.core.utils.toast @@ -64,7 +65,8 @@ class RoomSettingsFragment @Inject constructor( VectorBaseFragment(), RoomSettingsController.Callback, OnBackPressed, - GalleryOrCameraDialogHelper.Listener { + GalleryOrCameraDialogHelper.Listener, + VectorMenuProvider { private val viewModel: RoomSettingsViewModel by fragmentViewModel() private lateinit var roomProfileSharedActionViewModel: RoomProfileSharedActionViewModel 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 52778004e4..5684e941f1 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 @@ -34,6 +34,7 @@ import im.vector.app.R import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.extensions.safeOpenOutputStream import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.time.Clock import im.vector.app.core.utils.selectTxtFileToWrite import im.vector.app.databinding.FragmentDevtoolKeyrequestsBinding @@ -42,7 +43,8 @@ import javax.inject.Inject class KeyRequestsFragment @Inject constructor( private val clock: Clock, -) : VectorBaseFragment() { +) : VectorBaseFragment(), + VectorMenuProvider { override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentDevtoolKeyrequestsBinding { return FragmentDevtoolKeyrequestsBinding.inflate(inflater, container, false) 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 524a2a9fcc..da06f067c6 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 @@ -29,6 +29,7 @@ import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.databinding.FragmentGenericRecyclerBinding import org.matrix.android.sdk.api.session.pushers.Pusher import javax.inject.Inject @@ -36,7 +37,8 @@ import javax.inject.Inject // Referenced in vector_settings_notifications.xml class PushGatewaysFragment @Inject constructor( private val epoxyController: PushGateWayController -) : VectorBaseFragment() { +) : VectorBaseFragment(), + VectorMenuProvider { override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentGenericRecyclerBinding { return FragmentGenericRecyclerBinding.inflate(inflater, container, 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 671bfa48bb..3818f4278a 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 @@ -38,6 +38,7 @@ import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.resources.ColorProvider import im.vector.app.core.utils.colorizeMatchingText import im.vector.app.core.utils.isValidUrl @@ -67,7 +68,8 @@ class SpaceDirectoryFragment @Inject constructor( ) : VectorBaseFragment(), SpaceDirectoryController.InteractionListener, TimelineEventController.UrlClickCallback, - OnBackPressed { + OnBackPressed, + VectorMenuProvider { override fun getMenuRes() = R.menu.menu_space_directory 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 a01cfeb321..de1273b8d5 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 @@ -32,6 +32,7 @@ import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.utils.ToggleableAppBarLayoutBehavior import im.vector.app.databinding.FragmentSpaceLeaveAdvancedBinding import org.matrix.android.sdk.api.session.room.model.RoomSummary @@ -40,7 +41,8 @@ import javax.inject.Inject class SpaceLeaveAdvancedFragment @Inject constructor( val controller: SelectChildrenController ) : VectorBaseFragment(), - SelectChildrenController.Listener { + SelectChildrenController.Listener, + VectorMenuProvider { override fun getBinding(inflater: LayoutInflater, container: ViewGroup?) = FragmentSpaceLeaveAdvancedBinding.inflate(layoutInflater, container, false) @@ -49,6 +51,8 @@ class SpaceLeaveAdvancedFragment @Inject constructor( override fun getMenuRes() = R.menu.menu_space_leave + override fun handleMenuItemSelected(item: MenuItem) = false + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) 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 3e1d500ddc..848c17deb6 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 @@ -36,6 +36,7 @@ import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.databinding.FragmentSpaceAddRoomsBinding import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.debounce @@ -51,7 +52,9 @@ class SpaceAddRoomFragment @Inject constructor( private val roomEpoxyController: AddRoomListController, private val dmEpoxyController: AddRoomListController, ) : VectorBaseFragment(), - OnBackPressed, AddRoomListController.Listener { + OnBackPressed, + AddRoomListController.Listener, + VectorMenuProvider { override fun getBinding(inflater: LayoutInflater, container: ViewGroup?) = FragmentSpaceAddRoomsBinding.inflate(layoutInflater, container, false) 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 51bd884908..eb1de4fe60 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 @@ -37,6 +37,7 @@ import im.vector.app.core.extensions.configureWith import im.vector.app.core.intent.getFilenameFromUri import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.resources.ColorProvider import im.vector.app.core.time.Clock import im.vector.app.core.utils.toast @@ -66,7 +67,8 @@ class SpaceSettingsFragment @Inject constructor( ) : VectorBaseFragment(), SpaceSettingsController.Callback, GalleryOrCameraDialogHelper.Listener, - OnBackPressed { + OnBackPressed, + VectorMenuProvider { private val viewModel: RoomSettingsViewModel by fragmentViewModel() private val sharedViewModel: SpaceManageSharedViewModel by activityViewModel() 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 9790750368..b31833e37c 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 @@ -36,6 +36,7 @@ import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.setupAsSearch import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.utils.DimensionConverter import im.vector.app.core.utils.showIdentityServerConsentDialog import im.vector.app.core.utils.startSharePlainTextIntent @@ -54,7 +55,8 @@ class UserListFragment @Inject constructor( private val userListController: UserListController, private val dimensionConverter: DimensionConverter, ) : VectorBaseFragment(), - UserListController.Callback { + UserListController.Callback, + VectorMenuProvider { private val args: UserListFragmentArgs by args() private val viewModel: UserListViewModel by activityViewModel() 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 cd77902a8c..5501031e92 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 @@ -42,6 +42,7 @@ import im.vector.app.R import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.utils.openUrlInExternalBrowser import im.vector.app.databinding.FragmentRoomWidgetBinding import im.vector.app.features.webview.WebEventListener @@ -68,7 +69,8 @@ class WidgetFragment @Inject constructor( ) : VectorBaseFragment(), WebEventListener, - OnBackPressed { + OnBackPressed, + VectorMenuProvider { private val fragmentArgs: WidgetArgs by args() private val viewModel: WidgetViewModel by activityViewModel() From 1355178feebc617beffb4f0df91027a72c0cf788 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 4 Jul 2022 17:42:58 +0200 Subject: [PATCH 10/13] Fix compilation issue for Fragment --- .../java/im/vector/app/core/platform/VectorMenuProvider.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorMenuProvider.kt b/vector/src/main/java/im/vector/app/core/platform/VectorMenuProvider.kt index c94a2fcdb0..7508de5f72 100644 --- a/vector/src/main/java/im/vector/app/core/platform/VectorMenuProvider.kt +++ b/vector/src/main/java/im/vector/app/core/platform/VectorMenuProvider.kt @@ -28,10 +28,10 @@ interface VectorMenuProvider { fun getMenuRes(): Int // No op by default - fun handlePostCreateMenu(menu: Menu) = Unit + fun handlePostCreateMenu(menu: Menu) {} // No op by default - fun handlePrepareMenu(menu: Menu) = Unit + fun handlePrepareMenu(menu: Menu) {} fun handleMenuItemSelected(item: MenuItem): Boolean } From d43c802c90454bc246fe771419aadac056ebb5b5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 4 Jul 2022 17:48:35 +0200 Subject: [PATCH 11/13] Changelog --- changelog.d/6436.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/6436.misc diff --git a/changelog.d/6436.misc b/changelog.d/6436.misc new file mode 100644 index 0000000000..a170b624ce --- /dev/null +++ b/changelog.d/6436.misc @@ -0,0 +1 @@ +Let your Activity or Fragment implement `VectorMenuProvider` if they provide a menu. From 3e42cec4ec3cbe503dde48547958e0e4f981a0c7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 4 Jul 2022 21:15:38 +0200 Subject: [PATCH 12/13] Fix detekt issue. --- .../main/java/im/vector/app/core/platform/VectorMenuProvider.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorMenuProvider.kt b/vector/src/main/java/im/vector/app/core/platform/VectorMenuProvider.kt index 7508de5f72..05d710a185 100644 --- a/vector/src/main/java/im/vector/app/core/platform/VectorMenuProvider.kt +++ b/vector/src/main/java/im/vector/app/core/platform/VectorMenuProvider.kt @@ -21,7 +21,7 @@ import android.view.MenuItem import androidx.annotation.MenuRes /** - * Let your Activity of Fragment implement this interface if they provide a Menu + * Let your Activity of Fragment implement this interface if they provide a Menu. */ interface VectorMenuProvider { @MenuRes From 293a1771487d706111091d9d1d536439dcd5eea7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 4 Jul 2022 21:27:28 +0200 Subject: [PATCH 13/13] Quick rework, better to search for expected MenuItem --- .../features/devtools/RoomDevToolActivity.kt | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) 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 e848d0631f..774460eb1f 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 @@ -21,7 +21,6 @@ import android.content.Intent import android.os.Parcelable import android.view.Menu import android.view.MenuItem -import androidx.core.view.forEach import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import com.airbnb.mvrx.Fail @@ -182,19 +181,9 @@ class RoomDevToolActivity : 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 - } - it.isVisible = isVisible - } + menu.findItem(R.id.menuItemEdit).isVisible = state.displayMode == RoomDevToolViewState.Mode.StateEventDetail + menu.findItem(R.id.menuItemSend).isVisible = state.displayMode == RoomDevToolViewState.Mode.EditEventContent || + state.displayMode is RoomDevToolViewState.Mode.SendEventForm } }