@@ -20,10 +20,14 @@ package com.infomaniak.mail.ui.main.folder
20
20
import android.content.res.Configuration
21
21
import android.os.Bundle
22
22
import android.view.View
23
+ import androidx.annotation.ColorRes
24
+ import androidx.core.content.res.ResourcesCompat
25
+ import androidx.core.view.isGone
26
+ import androidx.core.view.isVisible
23
27
import androidx.fragment.app.Fragment
28
+ import androidx.fragment.app.FragmentContainerView
24
29
import androidx.fragment.app.activityViewModels
25
30
import androidx.navigation.fragment.findNavController
26
- import androidx.slidingpanelayout.widget.SlidingPaneLayout
27
31
import com.infomaniak.lib.core.utils.getBackNavigationResult
28
32
import com.infomaniak.lib.core.utils.safeNavigate
29
33
import com.infomaniak.mail.MatomoMail.OPEN_FROM_DRAFT_NAME
@@ -33,76 +37,46 @@ import com.infomaniak.mail.data.cache.mailboxContent.FolderController
33
37
import com.infomaniak.mail.data.models.thread.Thread
34
38
import com.infomaniak.mail.ui.MainActivity
35
39
import com.infomaniak.mail.ui.MainViewModel
36
- import com.infomaniak.mail.ui.main.NoAnimSlidingPaneLayout
37
40
import com.infomaniak.mail.ui.main.search.SearchFragment
38
41
import com.infomaniak.mail.ui.main.thread.ThreadFragment
39
- import com.infomaniak.mail.utils.UiUtils.FULLY_SLID
40
- import com.infomaniak.mail.utils.UiUtils.progressivelyColorSystemBars
41
- import com.infomaniak.mail.utils.extensions.AttachmentExtensions
42
- import com.infomaniak.mail.utils.extensions.safeNavigateToNewMessageActivity
43
- import com.infomaniak.mail.utils.extensions.setSystemBarsColors
42
+ import com.infomaniak.mail.utils.extensions.*
44
43
import javax.inject.Inject
45
44
46
45
abstract class TwoPaneFragment : Fragment () {
47
46
48
47
val mainViewModel: MainViewModel by activityViewModels()
49
48
protected val twoPaneViewModel: TwoPaneViewModel by activityViewModels()
50
49
51
- protected abstract val slidingPaneLayout: NoAnimSlidingPaneLayout
52
-
53
50
// TODO: When we'll update DragDropSwipeRecyclerViewLib, we'll need to make the adapter nullable.
54
51
// For now it causes a memory leak, because we can't remove the strong reference
55
52
// between the ThreadList's RecyclerView and its Adapter as it throws an NPE.
56
53
@Inject
57
54
lateinit var threadListAdapter: ThreadListAdapter
58
55
59
- private val leftStatusBarColor: Int by lazy {
60
- requireContext().getColor(if (this is ThreadListFragment ) R .color.backgroundHeaderColor else R .color.backgroundColor)
61
- }
62
- private val leftNavigationBarColor: Int by lazy { requireContext().getColor(R .color.backgroundColor) }
63
- private val rightStatusBarColor: Int by lazy { requireContext().getColor(R .color.backgroundColor) }
64
- private val rightNavigationBarColor: Int by lazy { requireContext().getColor(R .color.elevatedBackground) }
65
-
56
+ @ColorRes
57
+ abstract fun getStatusBarColor (): Int
58
+ abstract fun getLeftPane (): View ?
59
+ abstract fun getRightPane (): FragmentContainerView ?
66
60
abstract fun getAnchor (): View ?
67
61
open fun doAfterFolderChanged () = Unit
68
62
69
- fun isOnlyOneShown () = slidingPaneLayout.isSlideable
70
- fun areBothShown () = ! isOnlyOneShown()
71
- fun isOnlyLeftShown () = isOnlyOneShown() && ! slidingPaneLayout.isOpen
72
- fun isOnlyRightShown () = isOnlyOneShown() && slidingPaneLayout.isOpen
63
+ fun isOnlyOneShown (): Boolean = isPhone() || isTabletInPortrait()
64
+ fun isOnlyLeftShown (): Boolean = isOnlyOneShown() && ! twoPaneViewModel.isThreadOpen
65
+ fun isOnlyRightShown (): Boolean = isOnlyOneShown() && twoPaneViewModel.isThreadOpen
73
66
74
67
override fun onViewCreated (view : View , savedInstanceState : Bundle ? ) {
75
68
super .onViewCreated(view, savedInstanceState)
76
- setupSlidingPane ()
69
+ updateTwoPaneVisibilities ()
77
70
observeCurrentFolder()
78
71
observeThreadUid()
79
72
observeThreadNavigation()
80
73
}
81
74
82
75
override fun onConfigurationChanged (newConfig : Configuration ) {
83
76
super .onConfigurationChanged(newConfig)
77
+ updateTwoPaneVisibilities()
84
78
updateDrawerLockMode()
85
- ensureThreadIsDisplayed(newConfig.orientation)
86
- }
87
-
88
- private fun setupSlidingPane () = with (slidingPaneLayout) {
89
-
90
- lockMode = SlidingPaneLayout .LOCK_MODE_LOCKED
91
-
92
- addPanelSlideListener(object : SlidingPaneLayout .PanelSlideListener {
93
- override fun onPanelOpened (panel : View ) = Unit
94
- override fun onPanelClosed (panel : View ) = Unit
95
-
96
- override fun onPanelSlide (panel : View , slideOffset : Float ) {
97
- requireActivity().window.progressivelyColorSystemBars(
98
- slideOffset = FULLY_SLID - slideOffset,
99
- statusBarColorFrom = leftStatusBarColor,
100
- statusBarColorTo = rightStatusBarColor,
101
- navBarColorFrom = leftNavigationBarColor,
102
- navBarColorTo = rightNavigationBarColor,
103
- )
104
- }
105
- })
79
+ updateStatusBarColor()
106
80
}
107
81
108
82
private fun observeCurrentFolder () = with (twoPaneViewModel) {
@@ -128,13 +102,11 @@ abstract class TwoPaneFragment : Fragment() {
128
102
129
103
private fun observeThreadUid () {
130
104
twoPaneViewModel.currentThreadUid.observe(viewLifecycleOwner) { threadUid ->
105
+ updateTwoPaneVisibilities()
106
+ updateDrawerLockMode()
131
107
val isOpeningThread = threadUid != null
132
108
if (isOpeningThread) {
133
- val hasOpened = slidingPaneLayout.openPaneNoAnimation()
134
- if (hasOpened) {
135
- updateDrawerLockMode()
136
- setSystemBarsColors(statusBarColor = R .color.backgroundColor, navigationBarColor = null )
137
- }
109
+ if (isOnlyRightShown()) setSystemBarsColors(statusBarColor = R .color.backgroundColor, navigationBarColor = null )
138
110
} else {
139
111
resetPanes()
140
112
}
@@ -172,33 +144,72 @@ abstract class TwoPaneFragment : Fragment() {
172
144
173
145
private fun resetPanes () {
174
146
175
- val hasClosed = slidingPaneLayout.closePaneNoAnimation()
176
- updateDrawerLockMode()
177
-
178
- if (hasClosed) {
179
- setSystemBarsColors(
180
- statusBarColor = if (this @TwoPaneFragment is ThreadListFragment ) R .color.backgroundHeaderColor else null ,
181
- navigationBarColor = R .color.backgroundColor,
182
- )
147
+ if (isOnlyLeftShown()) {
148
+ setSystemBarsColors(statusBarColor = getStatusBarColor(), navigationBarColor = R .color.backgroundColor)
183
149
}
184
150
185
151
threadListAdapter.selectNewThread(newPosition = null , threadUid = null )
186
152
187
153
childFragmentManager.beginTransaction().replace(R .id.threadHostFragment, ThreadFragment ()).commit()
188
154
}
189
155
156
+ private fun updateTwoPaneVisibilities () {
157
+
158
+ val (leftWidth, rightWidth) = computeTwoPaneWidths(
159
+ widthPixels = requireActivity().application.resources.displayMetrics.widthPixels,
160
+ isThreadOpen = twoPaneViewModel.isThreadOpen,
161
+ )
162
+
163
+ getLeftPane()?.let { leftPane ->
164
+ if (leftWidth == 0 ) {
165
+ leftPane.isGone = true
166
+ } else {
167
+ if (leftPane.width != leftWidth) leftPane.layoutParams?.width = leftWidth
168
+ leftPane.isVisible = true
169
+ }
170
+ }
171
+
172
+ getRightPane()?.let { rightPane ->
173
+ if (rightWidth == 0 ) {
174
+ rightPane.isGone = true
175
+ } else {
176
+ if (rightPane.width != rightWidth) rightPane.layoutParams?.width = rightWidth
177
+ rightPane.isVisible = true
178
+ }
179
+ }
180
+ }
181
+
182
+ private fun computeTwoPaneWidths (widthPixels : Int , isThreadOpen : Boolean ): Pair <Int , Int > = with (twoPaneViewModel) {
183
+
184
+ val leftPaneWidthRatio = ResourcesCompat .getFloat(resources, R .dimen.leftPaneWidthRatio)
185
+ val rightPaneWidthRatio = ResourcesCompat .getFloat(resources, R .dimen.rightPaneWidthRatio)
186
+
187
+ return if (isTabletInLandscape()) {
188
+ (leftPaneWidthRatio * widthPixels).toInt() to (rightPaneWidthRatio * widthPixels).toInt()
189
+ } else {
190
+ if (isThreadOpen) 0 to widthPixels else widthPixels to 0
191
+ }
192
+ }
193
+
190
194
// TODO: When we'll add the feature of swiping between Threads, we'll need to check if this function is still needed.
191
195
private fun updateDrawerLockMode () {
192
196
if (this is ThreadListFragment ) {
193
- (requireActivity() as MainActivity ).setDrawerLockMode(
194
- isLocked = twoPaneViewModel.isInThreadInPhoneMode(requireContext()),
195
- )
197
+ (requireActivity() as MainActivity ).setDrawerLockMode(isLocked = isOnlyRightShown())
196
198
}
197
199
}
198
200
199
- private fun ensureThreadIsDisplayed (orientation : Int ) {
200
- if (orientation == Configuration .ORIENTATION_PORTRAIT && twoPaneViewModel.isInThreadInPhoneMode(requireContext())) {
201
- slidingPaneLayout.openPaneNoAnimation()
201
+ private fun updateStatusBarColor () {
202
+
203
+ val statusBarColor = if (isOnlyRightShown()) { // Thread (in Phone mode)
204
+ if (getRightPane()?.getFragment<ThreadFragment ?>()?.isScrolledToTheTop() == true ) {
205
+ R .color.toolbarLoweredColor
206
+ } else {
207
+ R .color.toolbarElevatedColor
208
+ }
209
+ } else { // ThreadList or Search
210
+ getStatusBarColor()
202
211
}
212
+
213
+ setSystemBarsColors(statusBarColor = statusBarColor, navigationBarColor = null )
203
214
}
204
215
}
0 commit comments