From b56207d9773880580c23c5ee39b68a7ee2cea6da Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Fri, 11 Feb 2022 11:08:59 -0400 Subject: [PATCH] Add requireListener and hierarchical error. --- .../app/subscription/boost/BoostFragment.kt | 4 +- .../currency/SetCurrencyFragment.kt | 4 +- .../subscribe/SubscribeFragment.kt | 4 +- .../forward/MultiselectForwardFragment.kt | 2 +- .../keyboard/KeyboardPagerFragment.kt | 1 + .../securesms/keyboard/ListenerExtensions.kt | 21 ------- .../emoji/EmojiKeyboardPageFragment.kt | 6 +- .../emoji/search/EmojiSearchFragment.kt | 6 +- .../keyboard/gif/GifKeyboardPageFragment.kt | 4 +- .../sticker/StickerKeyboardPageFragment.kt | 7 ++- .../sticker/StickerSearchDialogFragment.kt | 2 +- .../v2/gallery/MediaGalleryFragment.kt | 4 +- .../v2/review/MediaReviewFragment.kt | 4 +- .../scribbles/TextEntryDialogFragment.kt | 4 +- .../util/fragments/ListenerExtensions.kt | 57 +++++++++++++++++++ .../securesms/verify/VerifyScanFragment.kt | 4 +- 16 files changed, 86 insertions(+), 48 deletions(-) delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/keyboard/ListenerExtensions.kt create mode 100644 app/src/main/java/org/thoughtcrime/securesms/util/fragments/ListenerExtensions.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/boost/BoostFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/boost/BoostFragment.kt index 69c89c1ec8..0c0ce99500 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/boost/BoostFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/boost/BoostFragment.kt @@ -34,12 +34,12 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.models.Ne import org.thoughtcrime.securesms.components.settings.configure import org.thoughtcrime.securesms.components.settings.models.Progress import org.thoughtcrime.securesms.dependencies.ApplicationDependencies -import org.thoughtcrime.securesms.keyboard.findListener import org.thoughtcrime.securesms.util.BottomSheetUtil.requireCoordinatorLayout import org.thoughtcrime.securesms.util.CommunicationActions import org.thoughtcrime.securesms.util.LifecycleDisposable import org.thoughtcrime.securesms.util.Projection import org.thoughtcrime.securesms.util.SpanUtil +import org.thoughtcrime.securesms.util.fragments.requireListener import org.thoughtcrime.securesms.util.navigation.safeNavigate /** @@ -80,7 +80,7 @@ class BoostFragment : DSLSettingsBottomSheetFragment( } override fun bindAdapter(adapter: DSLSettingsAdapter) { - donationPaymentComponent = findListener()!! + donationPaymentComponent = requireListener() viewModel.refresh() CurrencySelection.register(adapter) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/currency/SetCurrencyFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/currency/SetCurrencyFragment.kt index 4c316eab79..519f2f684d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/currency/SetCurrencyFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/currency/SetCurrencyFragment.kt @@ -7,7 +7,7 @@ import org.thoughtcrime.securesms.components.settings.DSLSettingsBottomSheetFrag import org.thoughtcrime.securesms.components.settings.DSLSettingsText import org.thoughtcrime.securesms.components.settings.app.subscription.DonationPaymentComponent import org.thoughtcrime.securesms.components.settings.configure -import org.thoughtcrime.securesms.keyboard.findListener +import org.thoughtcrime.securesms.util.fragments.requireListener import java.util.Locale /** @@ -25,7 +25,7 @@ class SetCurrencyFragment : DSLSettingsBottomSheetFragment() { ) override fun bindAdapter(adapter: DSLSettingsAdapter) { - donationPaymentComponent = findListener()!! + donationPaymentComponent = requireListener() viewModel.state.observe(viewLifecycleOwner) { state -> adapter.submitList(getConfiguration(state).toMappingModelList()) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/subscribe/SubscribeFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/subscribe/SubscribeFragment.kt index 4e69ea892c..92726b9f11 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/subscribe/SubscribeFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/subscribe/SubscribeFragment.kt @@ -33,11 +33,11 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.models.Ne import org.thoughtcrime.securesms.components.settings.configure import org.thoughtcrime.securesms.components.settings.models.Progress import org.thoughtcrime.securesms.dependencies.ApplicationDependencies -import org.thoughtcrime.securesms.keyboard.findListener import org.thoughtcrime.securesms.payments.FiatMoneyUtil import org.thoughtcrime.securesms.subscription.Subscription import org.thoughtcrime.securesms.util.LifecycleDisposable import org.thoughtcrime.securesms.util.SpanUtil +import org.thoughtcrime.securesms.util.fragments.requireListener import org.thoughtcrime.securesms.util.navigation.safeNavigate import java.util.Calendar import java.util.Currency @@ -79,7 +79,7 @@ class SubscribeFragment : DSLSettingsFragment( } override fun bindAdapter(adapter: DSLSettingsAdapter) { - donationPaymentComponent = findListener()!! + donationPaymentComponent = requireListener() viewModel.refresh() BadgePreview.register(adapter) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/mutiselect/forward/MultiselectForwardFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/mutiselect/forward/MultiselectForwardFragment.kt index a632085801..4455012ba5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/mutiselect/forward/MultiselectForwardFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/mutiselect/forward/MultiselectForwardFragment.kt @@ -31,7 +31,6 @@ import org.thoughtcrime.securesms.components.FixedRoundedCornerBottomSheetDialog import org.thoughtcrime.securesms.contacts.ContactsCursorLoader import org.thoughtcrime.securesms.conversation.ui.error.SafetyNumberChangeDialog import org.thoughtcrime.securesms.database.model.IdentityRecord -import org.thoughtcrime.securesms.keyboard.findListener import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.sharing.MultiShareArgs @@ -41,6 +40,7 @@ import org.thoughtcrime.securesms.util.FeatureFlags import org.thoughtcrime.securesms.util.LifecycleDisposable import org.thoughtcrime.securesms.util.Util import org.thoughtcrime.securesms.util.ViewUtil +import org.thoughtcrime.securesms.util.fragments.findListener import org.thoughtcrime.securesms.util.views.SimpleProgressDialog import org.thoughtcrime.securesms.util.visible import org.whispersystems.libsignal.util.guava.Optional diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyboard/KeyboardPagerFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/keyboard/KeyboardPagerFragment.kt index 3b8124d2fc..2c63b3a901 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyboard/KeyboardPagerFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyboard/KeyboardPagerFragment.kt @@ -10,6 +10,7 @@ import org.thoughtcrime.securesms.components.emoji.MediaKeyboard import org.thoughtcrime.securesms.keyboard.emoji.EmojiKeyboardPageFragment import org.thoughtcrime.securesms.keyboard.gif.GifKeyboardPageFragment import org.thoughtcrime.securesms.keyboard.sticker.StickerKeyboardPageFragment +import org.thoughtcrime.securesms.util.fragments.findListener import org.thoughtcrime.securesms.util.visible import kotlin.reflect.KClass diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyboard/ListenerExtensions.kt b/app/src/main/java/org/thoughtcrime/securesms/keyboard/ListenerExtensions.kt deleted file mode 100644 index 74dffa0126..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/keyboard/ListenerExtensions.kt +++ /dev/null @@ -1,21 +0,0 @@ -package org.thoughtcrime.securesms.keyboard - -import androidx.fragment.app.Fragment - -/** - * Given an input type [T], find an instance of it first looking through all - * parents, and then the activity. - * - * @return First instance found of type [T] or null - */ -inline fun Fragment.findListener(): T? { - var parent: Fragment? = parentFragment - while (parent != null) { - if (parent is T) { - return parent - } - parent = parent.parentFragment - } - - return requireActivity() as? T -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/EmojiKeyboardPageFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/EmojiKeyboardPageFragment.kt index 6774c9f0be..935e0ac678 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/EmojiKeyboardPageFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/EmojiKeyboardPageFragment.kt @@ -14,9 +14,9 @@ import org.thoughtcrime.securesms.components.emoji.EmojiEventListener import org.thoughtcrime.securesms.components.emoji.EmojiPageView import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter.EmojiHeader -import org.thoughtcrime.securesms.keyboard.findListener import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.util.adapter.mapping.MappingModel +import org.thoughtcrime.securesms.util.fragments.requireListener import java.util.Optional private val DELETE_KEY_EVENT: KeyEvent = KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL) @@ -37,7 +37,7 @@ class EmojiKeyboardPageFragment : Fragment(R.layout.keyboard_pager_emoji_page_fr private val categoryUpdateOnScroll = UpdateCategorySelectionOnScroll() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - callback = requireNotNull(findListener()) + callback = requireNotNull(requireListener()) emojiPageView = view.findViewById(R.id.emoji_page_view) emojiPageView.initialize(this, this, true) @@ -85,7 +85,7 @@ class EmojiKeyboardPageFragment : Fragment(R.layout.keyboard_pager_emoji_page_fr viewModel.selectedKey.observe(viewLifecycleOwner) { updateCategoryTab(it) } - eventListener = findListener() ?: throw AssertionError("No emoji listener found") + eventListener = requireListener() } private fun updateCategoryTab(key: String) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/search/EmojiSearchFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/search/EmojiSearchFragment.kt index d0cfca19c5..bdd2aae481 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/search/EmojiSearchFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/search/EmojiSearchFragment.kt @@ -15,8 +15,8 @@ import org.thoughtcrime.securesms.components.emoji.EmojiEventListener import org.thoughtcrime.securesms.components.emoji.EmojiPageView import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter import org.thoughtcrime.securesms.keyboard.emoji.KeyboardPageSearchView -import org.thoughtcrime.securesms.keyboard.findListener import org.thoughtcrime.securesms.util.ViewUtil +import org.thoughtcrime.securesms.util.fragments.requireListener class EmojiSearchFragment : Fragment(R.layout.emoji_search_fragment), EmojiPageViewGridAdapter.VariationSelectorListener { @@ -26,7 +26,7 @@ class EmojiSearchFragment : Fragment(R.layout.emoji_search_fragment), EmojiPageV override fun onAttach(context: Context) { super.onAttach(context) - callback = findListener()!! + callback = requireListener() } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -36,7 +36,7 @@ class EmojiSearchFragment : Fragment(R.layout.emoji_search_fragment), EmojiPageV viewModel = ViewModelProvider(this, factory)[EmojiSearchViewModel::class.java] val keyboardAwareLinearLayout: KeyboardAwareLinearLayout = view.findViewById(R.id.kb_aware_layout) - val eventListener: EmojiEventListener = requireNotNull(findListener()) + val eventListener: EmojiEventListener = requireListener() val searchBar: KeyboardPageSearchView = view.findViewById(R.id.emoji_search_view) val resultsContainer: FrameLayout = view.findViewById(R.id.emoji_search_results_container) val noResults: TextView = view.findViewById(R.id.emoji_search_empty) diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyboard/gif/GifKeyboardPageFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/keyboard/gif/GifKeyboardPageFragment.kt index d5391259a4..1a60102328 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyboard/gif/GifKeyboardPageFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyboard/gif/GifKeyboardPageFragment.kt @@ -13,7 +13,7 @@ import org.thoughtcrime.securesms.giph.mp4.GiphyMp4Fragment import org.thoughtcrime.securesms.giph.mp4.GiphyMp4SaveResult import org.thoughtcrime.securesms.giph.mp4.GiphyMp4ViewModel import org.thoughtcrime.securesms.keyboard.emoji.KeyboardPageSearchView -import org.thoughtcrime.securesms.keyboard.findListener +import org.thoughtcrime.securesms.util.fragments.requireListener import org.thoughtcrime.securesms.util.views.SimpleProgressDialog class GifKeyboardPageFragment : LoggingFragment(R.layout.gif_keyboard_page_fragment) { @@ -28,7 +28,7 @@ class GifKeyboardPageFragment : LoggingFragment(R.layout.gif_keyboard_page_fragm private lateinit var quickSearchList: RecyclerView override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - host = findListener() ?: throw AssertionError("Parent fragment or activity must implement Host") + host = requireListener() childFragmentManager.beginTransaction() .replace(R.id.gif_keyboard_giphy_frame, GiphyMp4Fragment.create(host.isMms())) diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyboard/sticker/StickerKeyboardPageFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/keyboard/sticker/StickerKeyboardPageFragment.kt index d45e62f8b6..e5f516728c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyboard/sticker/StickerKeyboardPageFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyboard/sticker/StickerKeyboardPageFragment.kt @@ -15,7 +15,6 @@ import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.database.DatabaseObserver import org.thoughtcrime.securesms.dependencies.ApplicationDependencies import org.thoughtcrime.securesms.keyboard.emoji.KeyboardPageSearchView -import org.thoughtcrime.securesms.keyboard.findListener import org.thoughtcrime.securesms.mms.GlideApp import org.thoughtcrime.securesms.stickers.StickerEventListener import org.thoughtcrime.securesms.stickers.StickerRolloverTouchListener @@ -25,6 +24,8 @@ import org.thoughtcrime.securesms.util.InsetItemDecoration import org.thoughtcrime.securesms.util.Throttler import org.thoughtcrime.securesms.util.adapter.mapping.MappingModel import org.thoughtcrime.securesms.util.adapter.mapping.MappingModelList +import org.thoughtcrime.securesms.util.fragments.findListener +import org.thoughtcrime.securesms.util.fragments.requireListener import org.whispersystems.libsignal.util.Pair import java.util.Optional import kotlin.math.abs @@ -87,12 +88,12 @@ class StickerKeyboardPageFragment : view.findViewById(R.id.sticker_keyboard_search_text).callbacks = object : KeyboardPageSearchView.Callbacks { override fun onClicked() { - findListener()!!.openStickerSearch() + requireListener().openStickerSearch() } } view.findViewById(R.id.sticker_search).setOnClickListener { - findListener()!!.openStickerSearch() + requireListener().openStickerSearch() } view.findViewById(R.id.sticker_manage).setOnClickListener { findListener()?.onStickerManagementClicked() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyboard/sticker/StickerSearchDialogFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/keyboard/sticker/StickerSearchDialogFragment.kt index 07ca8c5509..8570ac58a5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyboard/sticker/StickerSearchDialogFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyboard/sticker/StickerSearchDialogFragment.kt @@ -12,12 +12,12 @@ import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.keyboard.emoji.KeyboardPageSearchView -import org.thoughtcrime.securesms.keyboard.findListener import org.thoughtcrime.securesms.mms.GlideApp import org.thoughtcrime.securesms.stickers.StickerEventListener import org.thoughtcrime.securesms.util.DeviceProperties import org.thoughtcrime.securesms.util.InsetItemDecoration import org.thoughtcrime.securesms.util.ViewUtil +import org.thoughtcrime.securesms.util.fragments.findListener import kotlin.math.max /** diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/gallery/MediaGalleryFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/gallery/MediaGalleryFragment.kt index a5919efbd9..dce7892a6a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/gallery/MediaGalleryFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/gallery/MediaGalleryFragment.kt @@ -13,13 +13,13 @@ import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.RecyclerView import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.components.recyclerview.GridDividerDecoration -import org.thoughtcrime.securesms.keyboard.findListener import org.thoughtcrime.securesms.mediasend.Media import org.thoughtcrime.securesms.mediasend.MediaRepository import org.thoughtcrime.securesms.mediasend.v2.MediaCountIndicatorButton import org.thoughtcrime.securesms.util.Stopwatch import org.thoughtcrime.securesms.util.ViewUtil import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter +import org.thoughtcrime.securesms.util.fragments.requireListener import org.thoughtcrime.securesms.util.livedata.LiveDataUtil import org.thoughtcrime.securesms.util.visible @@ -55,7 +55,7 @@ class MediaGalleryFragment : Fragment(R.layout.v2_media_gallery_fragment) { } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - callbacks = requireNotNull(findListener()) + callbacks = requireListener() toolbar = view.findViewById(R.id.media_gallery_toolbar) galleryRecycler = view.findViewById(R.id.media_gallery_grid) diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/review/MediaReviewFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/review/MediaReviewFragment.kt index f844947ef9..f4eee6f7b4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/review/MediaReviewFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/review/MediaReviewFragment.kt @@ -25,7 +25,6 @@ import io.reactivex.rxjava3.disposables.CompositeDisposable import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.conversation.mutiselect.forward.MultiselectForwardFragment import org.thoughtcrime.securesms.conversation.mutiselect.forward.MultiselectForwardFragmentArgs -import org.thoughtcrime.securesms.keyboard.findListener import org.thoughtcrime.securesms.mediasend.MediaSendActivityResult import org.thoughtcrime.securesms.mediasend.v2.HudCommand import org.thoughtcrime.securesms.mediasend.v2.MediaAnimations @@ -39,6 +38,7 @@ import org.thoughtcrime.securesms.permissions.Permissions import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.util.MediaUtil import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter +import org.thoughtcrime.securesms.util.fragments.requireListener import org.thoughtcrime.securesms.util.views.TouchInterceptingFrameLayout import org.thoughtcrime.securesms.util.visible @@ -81,7 +81,7 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { postponeEnterTransition() - callback = requireNotNull(findListener()) + callback = requireListener() drawToolButton = view.findViewById(R.id.draw_tool) cropAndRotateButton = view.findViewById(R.id.crop_and_rotate_tool) diff --git a/app/src/main/java/org/thoughtcrime/securesms/scribbles/TextEntryDialogFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/scribbles/TextEntryDialogFragment.kt index 3ecfbd9379..be08a3c18d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/scribbles/TextEntryDialogFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/scribbles/TextEntryDialogFragment.kt @@ -17,10 +17,10 @@ import org.signal.imageeditor.core.model.EditorElement import org.signal.imageeditor.core.renderers.MultiLineTextRenderer import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.components.KeyboardEntryDialogFragment -import org.thoughtcrime.securesms.keyboard.findListener import org.thoughtcrime.securesms.scribbles.HSVColorSlider.getColor import org.thoughtcrime.securesms.scribbles.HSVColorSlider.setUpForColor import org.thoughtcrime.securesms.util.ViewUtil +import org.thoughtcrime.securesms.util.fragments.requireListener class TextEntryDialogFragment : KeyboardEntryDialogFragment(R.layout.v2_media_image_editor_text_entry_fragment) { @@ -30,7 +30,7 @@ class TextEntryDialogFragment : KeyboardEntryDialogFragment(R.layout.v2_media_im private var colorIndicatorAlphaAnimator: Animator? = null override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - controller = requireNotNull(findListener()) + controller = requireListener() hiddenTextEntry = HiddenEditText(requireContext()) (view as ViewGroup).addView(hiddenTextEntry) diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/fragments/ListenerExtensions.kt b/app/src/main/java/org/thoughtcrime/securesms/util/fragments/ListenerExtensions.kt new file mode 100644 index 0000000000..9fce0bf626 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/util/fragments/ListenerExtensions.kt @@ -0,0 +1,57 @@ +package org.thoughtcrime.securesms.util.fragments + +import androidx.fragment.app.Fragment +import java.lang.Exception + +/** + * Given an input type [T], find an instance of it first looking through all + * parents, and then the activity. + * + * @return First instance found of type [T] or null + */ +inline fun Fragment.findListener(): T? { + var parent: Fragment? = parentFragment + while (parent != null) { + if (parent is T) { + return parent + } + parent = parent.parentFragment + } + + return requireActivity() as? T +} + +/** + * Given an input type [T], find an instance of it first looking through all parents, + * and then the activity. + * + * @return First instance found of type [T] + * @throws ListenerNotFoundException with the hierarchy searched. + * + */ +inline fun Fragment.requireListener(): T { + val hierarchy = mutableListOf() + try { + var parent: Fragment? = parentFragment + while (parent != null) { + if (parent is T) { + return parent + } + hierarchy.add(parent::class.java.name) + parent = parent.parentFragment + } + + return requireActivity() as T + } catch (e: ClassCastException) { + hierarchy.add(requireActivity()::class.java.name) + throw ListenerNotFoundException(hierarchy, e) + } +} + +class ListenerNotFoundException(hierarchy: List, cause: Throwable) : Exception(formatMessage(hierarchy), cause) { + companion object { + fun formatMessage(hierarchy: List): String { + return "Hierarchy Searched: \n${hierarchy.joinToString("\n")}" + } + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/verify/VerifyScanFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/verify/VerifyScanFragment.kt index 9c70dbd461..e27f5a3c6a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/verify/VerifyScanFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/verify/VerifyScanFragment.kt @@ -12,10 +12,10 @@ import androidx.fragment.app.Fragment import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.components.ShapeScrim import org.thoughtcrime.securesms.components.camera.CameraView -import org.thoughtcrime.securesms.keyboard.findListener import org.thoughtcrime.securesms.qr.ScanListener import org.thoughtcrime.securesms.qr.ScanningThread import org.thoughtcrime.securesms.util.ViewUtil +import org.thoughtcrime.securesms.util.fragments.requireListener /** * QR Scanner for identity verification @@ -29,7 +29,7 @@ class VerifyScanFragment : Fragment() { override fun onAttach(context: Context) { super.onAttach(context) - scanListener = findListener()!! + scanListener = requireListener() } override fun onCreateView(inflater: LayoutInflater, viewGroup: ViewGroup?, bundle: Bundle?): View? {