-
Notifications
You must be signed in to change notification settings - Fork 19
/
ConversationAssetMessagesViewModel.kt
134 lines (121 loc) 路 5.05 KB
/
ConversationAssetMessagesViewModel.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.wire.android.ui.home.conversations.media
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import com.wire.android.mapper.UIAssetMapper
import com.wire.android.navigation.SavedStateViewModel
import com.wire.android.ui.home.conversations.ConversationNavArgs
import com.wire.android.ui.navArgs
import com.wire.android.util.dispatchers.DispatcherProvider
import com.wire.kalium.logic.data.id.QualifiedID
import com.wire.kalium.logic.data.message.Message
import com.wire.kalium.logic.feature.asset.GetAssetMessagesForConversationUseCase
import com.wire.kalium.logic.feature.asset.GetMessageAssetUseCase
import com.wire.kalium.logic.feature.asset.MessageAssetResult
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject
@HiltViewModel
@Suppress("LongParameterList", "TooManyFunctions")
class ConversationAssetMessagesViewModel @Inject constructor(
override val savedStateHandle: SavedStateHandle,
private val dispatchers: DispatcherProvider,
private val getAssets: GetAssetMessagesForConversationUseCase,
private val getPrivateAsset: GetMessageAssetUseCase,
private val assetMapper: UIAssetMapper,
) : SavedStateViewModel(savedStateHandle) {
private val conversationNavArgs: ConversationNavArgs = savedStateHandle.navArgs()
val conversationId: QualifiedID = conversationNavArgs.conversationId
var viewState by mutableStateOf(ConversationAssetMessagesViewState())
private set
private var continueLoading = true
private var isLoading = false
private var currentOffset: Int = 0
init {
loadAssets()
}
fun continueLoading(shouldContinue: Boolean) {
if (shouldContinue) {
if (!continueLoading) {
continueLoading = true
loadAssets()
}
} else {
continueLoading = false
}
}
private fun loadAssets() = viewModelScope.launch {
if (isLoading) {
return@launch
}
isLoading = true
try {
while (continueLoading) {
val uiAssetList = withContext(dispatchers.io()) {
getAssets.invoke(
conversationId = conversationId,
limit = BATCH_SIZE,
offset = currentOffset
).map(assetMapper::toUIAsset)
}
// imitate loading new asset batch
viewState = viewState.copy(messages = viewState.messages.plus(uiAssetList.map {
it.copy(
downloadStatus = if (it.assetPath == null && it.downloadStatus != Message.DownloadStatus.FAILED_DOWNLOAD) {
Message.DownloadStatus.DOWNLOAD_IN_PROGRESS
} else {
it.downloadStatus
}
)
}).toImmutableList())
if (uiAssetList.size >= BATCH_SIZE) {
val uiMessages = uiAssetList.map { uiAsset ->
if (uiAsset.assetPath == null) {
val assetPath = withContext(dispatchers.io()) {
when (val asset = getPrivateAsset.invoke(uiAsset.conversationId, uiAsset.messageId).await()) {
is MessageAssetResult.Failure -> null
is MessageAssetResult.Success -> asset.decodedAssetPath
}
}
uiAsset.copy(assetPath = assetPath)
} else {
uiAsset
}
}
currentOffset += BATCH_SIZE
viewState = viewState.copy(
messages = viewState.messages.dropLast(uiMessages.size).plus(uiMessages).toImmutableList(),
)
} else {
continueLoading = false
}
}
} finally {
isLoading = false
}
}
companion object {
const val BATCH_SIZE = 5
}
}