Signal-Android/app/src/main/java/org/thoughtcrime/securesms/mediapreview/MediaPreviewV2ViewModel.kt

132 wiersze
4.5 KiB
Kotlin

package org.thoughtcrime.securesms.mediapreview
import android.content.Context
import android.content.Intent
import androidx.lifecycle.ViewModel
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import io.reactivex.rxjava3.schedulers.Schedulers
import org.thoughtcrime.securesms.attachments.AttachmentId
import org.thoughtcrime.securesms.attachments.DatabaseAttachment
import org.thoughtcrime.securesms.database.MediaTable
import org.thoughtcrime.securesms.mediasend.Media
import org.thoughtcrime.securesms.util.rx.RxStore
import java.util.Optional
class MediaPreviewV2ViewModel : ViewModel() {
private val store = RxStore(MediaPreviewV2State())
private val disposables = CompositeDisposable()
private val repository: MediaPreviewRepository = MediaPreviewRepository()
val state: Flowable<MediaPreviewV2State> = store.stateFlowable.observeOn(AndroidSchedulers.mainThread())
val currentPosition: Int
get() = store.state.position
fun setIsInSharedAnimation(isInSharedAnimation: Boolean) {
store.update { it.copy(isInSharedAnimation = isInSharedAnimation) }
}
fun fetchAttachments(context: Context, startingAttachmentId: AttachmentId, threadId: Long, sorting: MediaTable.Sorting, forceRefresh: Boolean = false) {
if (store.state.loadState == MediaPreviewV2State.LoadState.INIT || forceRefresh) {
disposables += store.update(repository.getAttachments(context, startingAttachmentId, threadId, sorting)) { result: MediaPreviewRepository.Result, oldState: MediaPreviewV2State ->
val albums = result.records.fold(mutableMapOf()) { acc: MutableMap<Long, MutableList<Media>>, mediaRecord: MediaTable.MediaRecord ->
val attachment = mediaRecord.attachment
if (attachment != null) {
val convertedMedia = mediaRecord.toMedia() ?: return@fold acc
acc.getOrPut(attachment.mmsId) { mutableListOf() }.add(convertedMedia)
}
acc
}
if (oldState.leftIsRecent) {
oldState.copy(
position = result.initialPosition,
mediaRecords = result.records,
messageBodies = result.messageBodies,
albums = albums,
loadState = MediaPreviewV2State.LoadState.DATA_LOADED
)
} else {
oldState.copy(
position = result.records.size - result.initialPosition - 1,
mediaRecords = result.records.reversed(),
messageBodies = result.messageBodies,
albums = albums.mapValues { it.value.reversed() },
loadState = MediaPreviewV2State.LoadState.DATA_LOADED
)
}
}
}
}
fun initialize(showThread: Boolean, allMediaInAlbumRail: Boolean, leftIsRecent: Boolean) {
if (store.state.loadState == MediaPreviewV2State.LoadState.INIT) {
store.update { oldState ->
oldState.copy(showThread = showThread, allMediaInAlbumRail = allMediaInAlbumRail, leftIsRecent = leftIsRecent)
}
}
}
fun setCurrentPage(position: Int) {
store.update { oldState ->
oldState.copy(position = position)
}
}
fun setMediaReady() {
store.update { oldState ->
oldState.copy(loadState = MediaPreviewV2State.LoadState.MEDIA_READY)
}
}
fun remoteDelete(attachment: DatabaseAttachment): Completable {
return repository.remoteDelete(attachment).subscribeOn(Schedulers.io())
}
fun localDelete(context: Context, attachment: DatabaseAttachment): Completable {
return repository.localDelete(context, attachment).subscribeOn(Schedulers.io())
}
fun jumpToFragment(context: Context, messageId: Long): Single<Intent> {
return repository.getMessagePositionIntent(context, messageId)
}
override fun onCleared() {
disposables.dispose()
store.dispose()
}
fun onDestroyView() {
store.update { oldState ->
oldState.copy(loadState = MediaPreviewV2State.LoadState.DATA_LOADED)
}
}
}
fun MediaTable.MediaRecord.toMedia(): Media? {
val attachment = this.attachment
val uri = attachment?.uri
if (attachment == null || uri == null) {
return null
}
return Media(
uri,
this.contentType,
this.date,
attachment.width,
attachment.height,
attachment.size,
0,
attachment.isBorderless,
attachment.isVideoGif,
Optional.empty(),
Optional.ofNullable(attachment.caption),
Optional.empty()
)
}