@@ -12,14 +12,14 @@ import android.view.View
1212import android.view.ViewGroup
1313import android.widget.Toast
1414import androidx.activity.result.ActivityResultLauncher
15+ import androidx.annotation.Discouraged
1516import androidx.annotation.StringRes
1617import androidx.appcompat.view.ActionMode
1718import androidx.compose.animation.animateContentSize
1819import androidx.compose.ui.Modifier
1920import androidx.compose.ui.layout.onSizeChanged
2021import androidx.compose.ui.platform.ComposeView
2122import androidx.coordinatorlayout.widget.CoordinatorLayout
22- import androidx.core.os.bundleOf
2323import androidx.core.view.ViewCompat
2424import androidx.core.view.WindowInsetsCompat
2525import androidx.core.view.WindowInsetsCompat.Type.systemBars
@@ -94,14 +94,14 @@ import net.thunderbird.core.featureflag.FeatureFlagKey
9494import net.thunderbird.core.featureflag.FeatureFlagProvider
9595import net.thunderbird.core.featureflag.FeatureFlagResult
9696import net.thunderbird.core.logging.Logger
97- import net.thunderbird.core.logging.legacy.Log
9897import net.thunderbird.core.outcome.Outcome
9998import net.thunderbird.core.preference.GeneralSettingsManager
10099import net.thunderbird.core.preference.display.visualSettings.message.list.DisplayMessageListSettings
101100import net.thunderbird.core.preference.interaction.InteractionSettings
102101import net.thunderbird.core.ui.theme.api.FeatureThemeProvider
103102import net.thunderbird.feature.account.avatar.AvatarMonogramCreator
104103import net.thunderbird.feature.mail.folder.api.OutboxFolderManager
104+ import net.thunderbird.feature.mail.message.list.MessageListFeatureFlags
105105import net.thunderbird.feature.mail.message.list.domain.DomainContract
106106import net.thunderbird.feature.mail.message.list.ui.dialog.SetupArchiveFolderDialogFragmentFactory
107107import net.thunderbird.feature.notification.api.content.InAppNotification
@@ -124,15 +124,29 @@ private const val MAXIMUM_MESSAGE_SORT_OVERRIDES = 3
124124private const val MINIMUM_CLICK_INTERVAL = 200L
125125private const val RECENT_CHANGES_SNACKBAR_DURATION = 10 * 1000
126126
127- private const val TAG = " MessageListFragment"
128-
129- @Suppress(" LargeClass" , " TooManyFunctions" )
130- class AbstractMessageListFragment :
127+ @Suppress(
128+ " LargeClass" ,
129+ " TooManyFunctions" ,
130+ " CyclomaticComplexMethod" ,
131+ " TooGenericExceptionCaught" ,
132+ " TooGenericExceptionThrown" ,
133+ " SwallowedException" ,
134+ " ReturnCount" ,
135+ " ForbiddenComment" ,
136+ )
137+ @Discouraged(
138+ message = " This class is in maintenance mode. DO NOT introduce any new features in this class. " +
139+ " Only bugfixes are allowed. New features must be introduced in the new MessageListFragment, " +
140+ " following the MVI principle." ,
141+ )
142+ abstract class AbstractMessageListFragment :
131143 Fragment (),
132144 ConfirmationDialogFragmentListener ,
133145 MessageListItemActionListener ,
134146 ErrorNotificationsDialogFragmentActionListener {
135147
148+ abstract val logTag: String
149+
136150 val viewModel: MessageListViewModel by viewModel()
137151 private val recentChangesViewModel: RecentChangesViewModel by viewModel()
138152
@@ -383,10 +397,10 @@ class AbstractMessageListFragment :
383397 setFragmentResultListener(
384398 SetupArchiveFolderDialogFragmentFactory .RESULT_CODE_DISMISS_REQUEST_KEY ,
385399 ) { key, bundle ->
386- Log .d(
400+ logger.debug(logTag) {
387401 " SetupArchiveFolderDialogFragment fragment listener triggered with " +
388- " key: $key and bundle: $bundle " ,
389- )
402+ " key: $key and bundle: $bundle "
403+ }
390404 loadMessageList(forceUpdate = true )
391405 }
392406 }
@@ -1618,7 +1632,7 @@ class AbstractMessageListFragment :
16181632 for ((folderId, messagesInFolder) in folderMap) {
16191633 val account = accountManager.getAccount(messagesInFolder.first().accountUuid)
16201634 if (account == null ) {
1621- logger.debug(TAG ) {
1635+ logger.debug(logTag ) {
16221636 " Account for message ${messagesInFolder.first()} not found, skipping copy/move operation"
16231637 }
16241638 continue
@@ -1743,12 +1757,12 @@ class AbstractMessageListFragment :
17431757 // If we represent a remote search, then kill that before going back.
17441758 if (isRemoteSearch && remoteSearchFuture != null ) {
17451759 try {
1746- Log .i( " Remote search in progress, attempting to abort..." )
1760+ logger.info(logTag) { " Remote search in progress, attempting to abort..." }
17471761
17481762 // Canceling the future stops any message fetches in progress.
17491763 val cancelSuccess = remoteSearchFuture!! .cancel(true ) // mayInterruptIfRunning = true
17501764 if (! cancelSuccess) {
1751- Log .e( " Could not cancel remote search future." )
1765+ logger.error(logTag) { " Could not cancel remote search future." }
17521766 }
17531767
17541768 // Closing the folder will kill off the connection if we're mid-search.
@@ -1763,7 +1777,7 @@ class AbstractMessageListFragment :
17631777 )
17641778 } catch (e: Exception ) {
17651779 // Since the user is going back, log and squash any exceptions.
1766- Log .e(e, " Could not abort remote search before going back" )
1780+ logger.error(logTag, e) { " Could not abort remote search before going back" }
17671781 }
17681782 }
17691783
@@ -2596,31 +2610,42 @@ class AbstractMessageListFragment :
25962610 }
25972611 }
25982612
2599- companion object Companion {
2600-
2601- private const val ARG_SEARCH = " searchObject"
2602- private const val ARG_THREADED_LIST = " showingThreadedList"
2603- private const val ARG_IS_THREAD_DISPLAY = " isThreadedDisplay"
2604-
2605- private const val STATE_SELECTED_MESSAGES = " selectedMessages"
2606- private const val STATE_ACTIVE_MESSAGES = " activeMessages"
2607- private const val STATE_ACTIVE_MESSAGE = " activeMessage"
2608- private const val STATE_REMOTE_SEARCH_PERFORMED = " remoteSearchPerformed"
2609-
2613+ /* *
2614+ * A factory for creating instances of [AbstractMessageListFragment].
2615+ *
2616+ * This interface is a temporary solution to toggle between different fragment implementations
2617+ * based on a feature flag. It allows for the creation of either a modern [MessageListFragment] or a
2618+ * [LegacyMessageListFragment] depending on the state of [MessageListFeatureFlags.EnableMessageListNewState].
2619+ */
2620+ interface Factory {
2621+ /* *
2622+ * Creates a new instance of a class that inherits from [AbstractMessageListFragment].
2623+ *
2624+ * The specific implementation returned ([MessageListFragment] or [LegacyMessageListFragment]) is determined
2625+ * by the [MessageListFeatureFlags.EnableMessageListNewState] feature flag.
2626+ *
2627+ * @param search The search query that defines which messages to display.
2628+ * @param isThreadDisplay `true` if the fragment is used to display a single thread, `false` otherwise.
2629+ * @param threadedList `true` to display the message list in a threaded conversation view, `false` otherwise.
2630+ *
2631+ * @return An instance of [MessageListFragment] if the new state feature flag is enabled;
2632+ * otherwise, an instance of [LegacyMessageListFragment].
2633+ */
26102634 fun newInstance (
26112635 search : LocalMessageSearch ,
26122636 isThreadDisplay : Boolean ,
26132637 threadedList : Boolean ,
2614- ): AbstractMessageListFragment {
2615- val searchBytes = LocalMessageSearchSerializer .serialize(search)
2616-
2617- return AbstractMessageListFragment ().apply {
2618- arguments = bundleOf(
2619- ARG_SEARCH to searchBytes,
2620- ARG_IS_THREAD_DISPLAY to isThreadDisplay,
2621- ARG_THREADED_LIST to threadedList,
2622- )
2623- }
2624- }
2638+ ): AbstractMessageListFragment
2639+ }
2640+
2641+ companion object {
2642+ protected const val ARG_SEARCH = " searchObject"
2643+ protected const val ARG_THREADED_LIST = " showingThreadedList"
2644+ protected const val ARG_IS_THREAD_DISPLAY = " isThreadedDisplay"
2645+
2646+ protected const val STATE_SELECTED_MESSAGES = " selectedMessages"
2647+ protected const val STATE_ACTIVE_MESSAGES = " activeMessages"
2648+ protected const val STATE_ACTIVE_MESSAGE = " activeMessage"
2649+ protected const val STATE_REMOTE_SEARCH_PERFORMED = " remoteSearchPerformed"
26252650 }
26262651}
0 commit comments