@@ -67,6 +67,7 @@ import com.infomaniak.mail.ui.MainActivity
6767import com.infomaniak.mail.ui.alertDialogs.DescriptionAlertDialog
6868import com.infomaniak.mail.ui.alertDialogs.TitleAlertDialog
6969import com.infomaniak.mail.ui.main.SnackbarManager
70+ import com.infomaniak.mail.ui.main.folder.ThreadListViewModel.ContentDisplayMode
7071import com.infomaniak.mail.ui.main.settings.appearance.swipe.SwipeActionsSettingsFragment
7172import com.infomaniak.mail.ui.main.thread.ThreadFragment
7273import com.infomaniak.mail.ui.newMessage.NewMessageActivityArgs
@@ -80,8 +81,6 @@ import com.infomaniak.mail.utils.Utils.isPermanentDeleteFolder
8081import com.infomaniak.mail.utils.Utils.runCatchingRealm
8182import com.infomaniak.mail.utils.extensions.*
8283import dagger.hilt.android.AndroidEntryPoint
83- import io.sentry.Sentry
84- import io.sentry.SentryLevel
8584import kotlinx.coroutines.launch
8685import java.util.Date
8786import javax.inject.Inject
@@ -164,6 +163,7 @@ class ThreadListFragment : TwoPaneFragment(), SwipeRefreshLayout.OnRefreshListen
164163 observeUpdateInstall()
165164 observeWebViewOutdated()
166165 observeLoadMoreTriggers()
166+ observeContentDisplayMode()
167167 }.getOrDefault(Unit )
168168
169169 @ColorRes
@@ -706,46 +706,60 @@ class ThreadListFragment : TwoPaneFragment(), SwipeRefreshLayout.OnRefreshListen
706706
707707 private fun updateThreadsVisibility () = with (threadListViewModel) {
708708
709- fun displayThreadsView (
710- areThereThreads : Boolean ,
711- isFilterEnabled : Boolean ,
712- isBooting : Boolean ,
713- isWaitingFirstThreads : Boolean ,
714- ) {
709+ val isNetworkConnected = mainViewModel.hasNetwork
715710
716- with (binding) {
717- emptyStateView.isGone = true
718- threadsList.isVisible = true
719- }
711+ // The folder's cursor is null, meaning it's the 1st time we are opening this folder.
712+ val isCursorNull = currentFolderCursor == null
720713
721- if (! areThereThreads && ! isFilterEnabled && ! isBooting && ! isWaitingFirstThreads) {
722- val currentFolder = mainViewModel.currentFolder.value
723- Sentry .captureMessage(
724- " Should display threads is true but there are no threads to display" ,
725- SentryLevel .WARNING ,
726- ) { scope ->
727- scope.setExtra(" cursor" , " $currentFolderCursor " )
728- scope.setExtra(" folderRole" , currentFolder?.role?.name.toString())
729- scope.setExtra(" folderThreadsCount" , " ${currentFolder?.threads?.count()} " )
730- }
731- }
732- }
714+ // We have a cursor, but don't have any info about threads yet, meaning the app is still booting and loading things.
715+ val isBooting = ! isCursorNull && currentThreadsCount == null
733716
734- val areThereThreads = (currentThreadsCount ? : 0 ) > 0
717+ // We know that there is existing threads in this folder, so if we wait long enough, they'll be there.
718+ val areThereThreadsSoon = mainViewModel.currentFolderLive.value?.oldMessagesUidsToFetch?.isNotEmpty() == true
719+
720+ // If there is network connectivity, but we either don't have a cursor yet
721+ // or don't have threads yet (but we know that they are coming), it means
722+ // we are opening this folder for the 1st time and we know we'll have a result at the end.
723+ val isWaitingFirstThreads = (isCursorNull || areThereThreadsSoon) && isNetworkConnected
724+
725+ // There is at least 1 thread available to be displayed right now.
726+ val areThereThreadsNow = (currentThreadsCount ? : 0 ) > 0
727+
728+ // If we filtered on something, it means we have threads, so we want to display the Threads display mode.
735729 val isFilterEnabled = mainViewModel.currentFilter.value != ThreadFilter .ALL
736- val isCursorNull = currentFolderCursor == null
737- val isNetworkConnected = mainViewModel.hasNetwork
738- val isBooting = currentThreadsCount == null && ! isCursorNull && isNetworkConnected
739- val isWaitingFirstThreads = isCursorNull && isNetworkConnected
740- val shouldDisplayThreadsView = isBooting || isWaitingFirstThreads || areThereThreads || isFilterEnabled
741730
742- when {
743- shouldDisplayThreadsView -> displayThreadsView(areThereThreads, isFilterEnabled, isBooting, isWaitingFirstThreads)
744- isCursorNull || ! isNetworkConnected -> setEmptyState(EmptyState .NETWORK )
745- isCurrentFolderRole(FolderRole .INBOX ) -> setEmptyState(EmptyState .INBOX )
746- isCurrentFolderRole(FolderRole .TRASH ) -> setEmptyState(EmptyState .TRASH )
747- else -> setEmptyState(EmptyState .FOLDER )
731+ // If any of these conditions is true, it means Threads are on their way or the
732+ // app is still loading things, so either way we want to display the Threads mode.
733+ val shouldDisplayThreadsView = isBooting || isWaitingFirstThreads || areThereThreadsNow || isFilterEnabled
734+
735+ contentDisplayMode.value = when {
736+ shouldDisplayThreadsView -> ContentDisplayMode .Threads
737+ ! isNetworkConnected -> ContentDisplayMode .NoNetwork
738+ else -> ContentDisplayMode .EmptyFolder
739+ }
740+ }
741+
742+ private fun observeContentDisplayMode () {
743+
744+ fun folderEmptyState () = when {
745+ isCurrentFolderRole(FolderRole .INBOX ) -> EmptyState .INBOX
746+ isCurrentFolderRole(FolderRole .TRASH ) -> EmptyState .TRASH
747+ else -> EmptyState .FOLDER
748748 }
749+
750+ threadListViewModel.contentDisplayMode
751+ .observe(viewLifecycleOwner) {
752+ when (it) {
753+ ContentDisplayMode .Threads , null -> displayThreadsView()
754+ ContentDisplayMode .NoNetwork -> setEmptyState(EmptyState .NETWORK )
755+ ContentDisplayMode .EmptyFolder -> setEmptyState(folderEmptyState())
756+ }
757+ }
758+ }
759+
760+ private fun displayThreadsView () = with (binding) {
761+ emptyStateView.isGone = true
762+ threadsList.isVisible = true
749763 }
750764
751765 private fun setEmptyState (emptyState : EmptyState ): Unit = with (binding) {
0 commit comments