@@ -137,7 +137,7 @@ class ThreadViewModel @Inject constructor(
137
137
138
138
fun reassignMessagesLiveWithoutSuperCollapsedBlock (messageUid : String ) {
139
139
reassignMessages {
140
- messageController.getMessagesAsync(messageUid).map { mapRealmMessagesResult (it.list) }
140
+ messageController.getMessagesAsync(messageUid).map { mapRealmMessagesResultWithoutSuperCollapsedBlock (it.list) }
141
141
}
142
142
}
143
143
@@ -148,99 +148,59 @@ class ThreadViewModel @Inject constructor(
148
148
}
149
149
}
150
150
151
- private suspend fun mapRealmMessagesResult (messages : RealmResults <Message >): Pair <ThreadAdapterItems , MessagesWithoutHeavyData > {
152
-
153
- val items = mutableListOf<Any >()
154
- val messagesToFetch = mutableListOf<Message >()
155
-
156
- messages.forEach { message ->
157
- splitBody(message).let {
158
- items + = it
159
- if (! it.isFullyDownloaded()) messagesToFetch + = it
160
- }
161
- }
162
-
163
- return items to messagesToFetch
164
- }
165
-
166
151
private suspend fun mapRealmMessagesResult (
167
152
messages : RealmResults <Message >,
168
153
threadUid : String ,
169
154
): Pair <ThreadAdapterItems , MessagesWithoutHeavyData > {
170
155
171
156
superCollapsedBlock = superCollapsedBlock ? : SuperCollapsedBlock ()
172
157
173
- val items = mutableListOf<Any >()
174
- val messagesToFetch = mutableListOf<Message >()
175
- val thread = messages.firstOrNull()?.threads?.firstOrNull { it.uid == threadUid } ? : return items to messagesToFetch
158
+ val thread = messages.first().threads.single { it.uid == threadUid }
176
159
val firstIndexAfterBlock = computeFirstIndexAfterBlock(thread, messages)
177
160
superCollapsedBlock!! .shouldBeDisplayed = shouldBlockBeDisplayed(messages.count(), firstIndexAfterBlock)
178
161
179
- suspend fun addMessage (message : Message ) {
180
- splitBody(message).let {
181
- items + = it
182
- if (! it.isFullyDownloaded()) messagesToFetch + = it
183
- }
184
- }
185
-
186
- suspend fun mapListWithNewBlock () {
187
- messages.forEachIndexed { index, message ->
162
+ suspend fun mapListWithNewBlock (): Pair <ThreadAdapterItems , MessagesWithoutHeavyData > {
163
+ return formatLists(messages) { index, _ ->
188
164
when (index) {
189
- 0 -> { // First Message
190
- addMessage(message)
191
- }
192
- in 1 .. < firstIndexAfterBlock -> { // All Messages that should go in block
193
- superCollapsedBlock!! .messagesUids.add(message.uid)
194
- }
195
- firstIndexAfterBlock -> { // First Message not in block
196
- items + = superCollapsedBlock!!
197
- addMessage(message.apply { shouldHideDivider = true })
198
- }
199
- else -> { // All following Messages
200
- addMessage(message)
201
- }
165
+ 0 -> MessageBehavior .DISPLAYED // First Message
166
+ in 1 until firstIndexAfterBlock -> MessageBehavior .COLLAPSED // All Messages that should go in block
167
+ firstIndexAfterBlock -> MessageBehavior .FIRST_AFTER_BLOCK // First Message not in block
168
+ else -> MessageBehavior .DISPLAYED // All following Messages
202
169
}
203
170
}
204
171
}
205
172
206
- suspend fun mapListWithExistingBlock () {
173
+ suspend fun mapListWithExistingBlock (): Pair < ThreadAdapterItems , MessagesWithoutHeavyData > {
207
174
208
175
var isStillInBlock = true
209
176
val previousBlock = superCollapsedBlock!! .messagesUids.toSet()
210
177
211
178
superCollapsedBlock!! .messagesUids.clear()
212
179
213
- messages.forEachIndexed { index, message ->
180
+ return formatLists( messages) { index, messageUid ->
214
181
when {
215
- index == 0 -> { // First Message
216
- addMessage(message)
217
- }
218
- previousBlock.contains(message.uid) && isStillInBlock -> { // All Messages already in block
219
- superCollapsedBlock!! .messagesUids.add(message.uid)
220
- }
221
- ! previousBlock.contains(message.uid) && isStillInBlock -> { // First Message not in block
182
+ index == 0 -> MessageBehavior .DISPLAYED // First Message
183
+ previousBlock.contains(messageUid) && isStillInBlock -> MessageBehavior .COLLAPSED // All Messages already in block
184
+ ! previousBlock.contains(messageUid) && isStillInBlock -> { // First Message not in block
222
185
isStillInBlock = false
223
- items + = superCollapsedBlock!!
224
- addMessage(message.apply { shouldHideDivider = true })
225
- }
226
- else -> { // All following Messages
227
- addMessage(message)
186
+ MessageBehavior .FIRST_AFTER_BLOCK
228
187
}
188
+ else -> MessageBehavior .DISPLAYED // All following Messages
229
189
}
230
190
}
231
191
}
232
192
233
- suspend fun mapFullList () {
234
- messages.forEach { addMessage(it) }
235
- }
236
-
237
- if (superCollapsedBlock!! .shouldBeDisplayed) {
193
+ return if (superCollapsedBlock!! .shouldBeDisplayed) {
238
194
if (superCollapsedBlock!! .isFirstTime()) mapListWithNewBlock() else mapListWithExistingBlock()
239
195
} else {
240
- mapFullList()
196
+ formatLists(messages) { _, _ -> MessageBehavior . DISPLAYED }
241
197
}
198
+ }
242
199
243
- return items to messagesToFetch
200
+ private suspend fun mapRealmMessagesResultWithoutSuperCollapsedBlock (
201
+ messages : RealmResults <Message >,
202
+ ): Pair <ThreadAdapterItems , MessagesWithoutHeavyData > {
203
+ return formatLists(messages) { _, _ -> MessageBehavior .DISPLAYED }
244
204
}
245
205
246
206
private fun computeFirstIndexAfterBlock (thread : Thread , list : RealmResults <Message >): Int {
@@ -266,6 +226,40 @@ class ThreadViewModel @Inject constructor(
266
226
firstIndexAfterBlock >= SUPER_COLLAPSED_BLOCK_FIRST_INDEX_LIMIT // At least 2 Messages in the Block
267
227
}
268
228
229
+ // If we add a fourth case in the `when`, don't forget to add a fourth 'o' in the function name.
230
+ private suspend fun formatLists (
231
+ messages : List <Message >,
232
+ computeBehavior : (Int , String ) -> MessageBehavior ,
233
+ ): Pair <MutableList <Any >, MutableList<Message>> {
234
+
235
+ val items = mutableListOf<Any >()
236
+ val messagesToFetch = mutableListOf<Message >()
237
+
238
+ suspend fun addMessage (message : Message ) {
239
+ splitBody(message).let {
240
+ items + = it
241
+ if (! it.isFullyDownloaded()) messagesToFetch + = it
242
+ }
243
+ }
244
+
245
+ messages.forEachIndexed { index, message ->
246
+ when (computeBehavior(index, message.uid)) {
247
+ MessageBehavior .DISPLAYED -> {
248
+ addMessage(message)
249
+ }
250
+ MessageBehavior .COLLAPSED -> {
251
+ superCollapsedBlock!! .messagesUids.add(message.uid)
252
+ }
253
+ MessageBehavior .FIRST_AFTER_BLOCK -> {
254
+ items + = superCollapsedBlock!!
255
+ addMessage(message.apply { shouldHideDivider = true })
256
+ }
257
+ }
258
+ }
259
+
260
+ return items to messagesToFetch
261
+ }
262
+
269
263
private suspend fun splitBody (message : Message ): Message = withContext(ioDispatcher) {
270
264
if (message.body == null ) return @withContext message
271
265
@@ -460,6 +454,12 @@ class ThreadViewModel @Inject constructor(
460
454
val menuId : Int ,
461
455
)
462
456
457
+ private enum class MessageBehavior {
458
+ DISPLAYED ,
459
+ COLLAPSED ,
460
+ FIRST_AFTER_BLOCK ,
461
+ }
462
+
463
463
companion object {
464
464
private const val SUPER_COLLAPSED_BLOCK_MINIMUM_MESSAGES_LIMIT = 5
465
465
private const val SUPER_COLLAPSED_BLOCK_FIRST_INDEX_LIMIT = 3
0 commit comments