Skip to content

Commit

Permalink
Merge pull request #189 from Infomaniak/use-remember-with-key-for-tra…
Browse files Browse the repository at this point in the history
…nsfer-info

fix: Use UiState pattern to load TransferDetailsScreen
  • Loading branch information
tevincent authored Nov 27, 2024
2 parents 5d13003 + c1c08d4 commit 2497eb2
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import com.infomaniak.swisstransfer.ui.images.icons.QrCode
import com.infomaniak.swisstransfer.ui.images.icons.Share
import com.infomaniak.swisstransfer.ui.previewparameter.TransferUiListPreviewParameter
import com.infomaniak.swisstransfer.ui.screen.main.components.SmallWindowTopAppBarScaffold
import com.infomaniak.swisstransfer.ui.screen.main.transferdetails.TransferDetailsViewModel.TransferDetailsUiState.*
import com.infomaniak.swisstransfer.ui.screen.main.transferdetails.components.PasswordBottomSheet
import com.infomaniak.swisstransfer.ui.screen.main.transferdetails.components.QrCodeBottomSheet
import com.infomaniak.swisstransfer.ui.screen.main.transferdetails.components.TransferInfo
Expand All @@ -63,19 +64,20 @@ fun TransferDetailsScreen(
navigateBack: (() -> Unit)?,
transferDetailsViewModel: TransferDetailsViewModel = hiltViewModel<TransferDetailsViewModel>(),
) {
val transfer by transferDetailsViewModel.transfer.collectAsStateWithLifecycle()
val isLoading by remember { derivedStateOf { transfer == null } }
val uiState by transferDetailsViewModel.uiState.collectAsStateWithLifecycle()

LaunchedEffect(transferUuid) {
transferDetailsViewModel.loadTransfer(transferUuid)
}

if (!isLoading) {
if (uiState is Delete) {
navigateBack?.invoke()
} else if (uiState is Success) {
TransferDetailsScreen(
transferUrl = transferDetailsViewModel.getTransferUrl(transferUuid),
direction = direction,
navigateBack = navigateBack,
getTransfer = { transfer },
getTransfer = { (uiState as Success).transfer },
getCheckedFiles = { transferDetailsViewModel.checkedFiles },
clearCheckedFiles = { transferDetailsViewModel.checkedFiles.clear() },
setFileCheckStatus = { fileUid, isChecked ->
Expand All @@ -90,14 +92,13 @@ private fun TransferDetailsScreen(
transferUrl: String,
direction: TransferDirection,
navigateBack: (() -> Unit)?,
getTransfer: () -> TransferUi?,
getTransfer: () -> TransferUi,
getCheckedFiles: () -> SnapshotStateMap<String, Boolean>,
clearCheckedFiles: () -> Unit,
setFileCheckStatus: (String, Boolean) -> Unit,
) {

val context = LocalContext.current
val transfer = getTransfer() ?: return
val transferRecipients: List<String> = emptyList() // TODO: Use real data
val transferPassword = "toto42" // TODO: Use real data

Expand All @@ -108,7 +109,7 @@ private fun TransferDetailsScreen(
SmallWindowTopAppBarScaffold(
smallWindowTopAppBar = {
SwissTransferTopAppBar(
title = transfer.createdDateTimestamp.toDateFromSeconds().format(FORMAT_DATE_FULL),
title = getTransfer().createdDateTimestamp.toDateFromSeconds().format(FORMAT_DATE_FULL),
navigationMenu = TopAppBarButton.backButton(navigateBack ?: {}),
TopAppBarButton.downloadButton { /* TODO */ },
)
Expand All @@ -117,7 +118,7 @@ private fun TransferDetailsScreen(
) {
Column {

FilesList(transfer, transferRecipients, isMultiselectOn, getCheckedFiles, setFileCheckStatus)
FilesList(getTransfer, transferRecipients, isMultiselectOn, getCheckedFiles, setFileCheckStatus)

BottomBar(
direction = direction,
Expand Down Expand Up @@ -156,33 +157,33 @@ private fun TransferDetailsScreen(

@Composable
private fun ColumnScope.FilesList(
transfer: TransferUi,
getTransfer: () -> TransferUi,
transferRecipients: List<String>,
isMultiselectOn: Boolean,
getCheckedFiles: () -> SnapshotStateMap<String, Boolean>,
setFileCheckStatus: (String, Boolean) -> Unit,
) {

val shouldDisplayRecipients = transferRecipients.isNotEmpty()
val shouldDisplayMessage = transfer.message != null
val shouldDisplayMessage = getTransfer().message != null

FileItemList(
modifier = Modifier
.weight(1.0f)
.padding(horizontal = Margin.Medium),
files = transfer.files,
files = getTransfer().files,
isRemoveButtonVisible = false,
isCheckboxVisible = { isMultiselectOn },
isUidChecked = { fileUid -> getCheckedFiles()[fileUid] ?: false },
setUidCheckStatus = { fileUid, isChecked -> setFileCheckStatus(fileUid, isChecked) },
header = {
Column {
Spacer(Modifier.height(Margin.Large))
TransferInfo(transfer)
TransferInfo(getTransfer)
Spacer(Modifier.height(Margin.Large))
if (shouldDisplayRecipients) TransferRecipients(transferRecipients)
if (shouldDisplayRecipients && shouldDisplayMessage) Spacer(Modifier.height(Margin.Mini))
if (shouldDisplayMessage) TransferMessage(transfer.message!!)
if (shouldDisplayMessage) TransferMessage(getTransfer().message!!)
if (shouldDisplayRecipients || shouldDisplayMessage) Spacer(Modifier.height(Margin.Large))
TransferContentHeader()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,17 @@
*/
package com.infomaniak.swisstransfer.ui.screen.main.transferdetails

import androidx.compose.runtime.Immutable
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.snapshots.SnapshotStateMap
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.infomaniak.multiplatform_swisstransfer.SharedApiUrlCreator
import com.infomaniak.multiplatform_swisstransfer.common.interfaces.ui.TransferUi
import com.infomaniak.multiplatform_swisstransfer.managers.TransferManager
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import javax.inject.Inject

Expand All @@ -41,9 +40,15 @@ class TransferDetailsViewModel @Inject constructor(
private val _transferUuidFlow = MutableSharedFlow<String>(1)

@OptIn(ExperimentalCoroutinesApi::class)
val transfer = _transferUuidFlow
val uiState = _transferUuidFlow
.flatMapLatest { transferManager.getTransferFlow(it) }
.stateIn(viewModelScope, SharingStarted.Eagerly, null)
.map { transfer ->
when (transfer) {
null -> TransferDetailsUiState.Delete
else -> TransferDetailsUiState.Success(transfer)
}
}
.stateIn(viewModelScope, SharingStarted.Eagerly, TransferDetailsUiState.Loading)

val checkedFiles: SnapshotStateMap<String, Boolean> = mutableStateMapOf()

Expand All @@ -54,4 +59,16 @@ class TransferDetailsViewModel @Inject constructor(
}

fun getTransferUrl(transferUuid: String): String = sharedApiUrlCreator.shareTransferUrl(transferUuid)

sealed class TransferDetailsUiState {

@Immutable
data class Success(val transfer: TransferUi) : TransferDetailsUiState()

@Immutable
data object Loading : TransferDetailsUiState()

@Immutable
data object Delete : TransferDetailsUiState()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,13 @@ import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme
import com.infomaniak.swisstransfer.ui.utils.PreviewLightAndDark

@Composable
fun TransferInfo(transfer: TransferUi) {
fun TransferInfo(getTransfer: () -> TransferUi) {

val filesCount = transfer.files.count()
val downloadedCount by remember { derivedStateOf { transfer.downloadLimit - transfer.downloadLeft } }
val filesCount by remember { derivedStateOf { getTransfer().files.count() } }
val downloadedCount by remember { derivedStateOf { getTransfer().downloadLimit - getTransfer().downloadLeft } }
val expiresInDays by remember { derivedStateOf { getTransfer().expiresInDays } }
val downloadLimit by remember { derivedStateOf { getTransfer().downloadLimit } }
val sizeUploaded by remember { derivedStateOf { getTransfer().sizeUploaded } }

Row(verticalAlignment = Alignment.CenterVertically) {
Icon(
Expand All @@ -62,7 +65,7 @@ fun TransferInfo(transfer: TransferUi) {
Spacer(Modifier.width(Margin.Mini))
TextDotText(
firstText = { pluralStringResource(R.plurals.filesCount, filesCount, filesCount) },
secondText = { Formatter.formatShortFileSize(LocalContext.current, transfer.sizeUploaded) },
secondText = { Formatter.formatShortFileSize(LocalContext.current, sizeUploaded) },
color = SwissTransferTheme.colors.primaryTextColor,
)
}
Expand All @@ -71,14 +74,14 @@ fun TransferInfo(transfer: TransferUi) {

IconText(
icon = AppIcons.Clock,
text = stringResource(R.string.expiresIn, transfer.expiresInDays),
text = stringResource(R.string.expiresIn, expiresInDays),
)

HorizontalDivider(modifier = Modifier.padding(vertical = Margin.Medium))

IconText(
icon = AppIcons.ArrowDownFile,
text = stringResource(R.string.downloadedTransferLabel, downloadedCount, transfer.downloadLimit),
text = stringResource(R.string.downloadedTransferLabel, downloadedCount, downloadLimit),
)
}

Expand Down Expand Up @@ -106,7 +109,7 @@ private fun Preview(@PreviewParameter(TransferUiListPreviewParameter::class) tra
SwissTransferTheme {
Surface {
Column {
TransferInfo(transfers.first())
TransferInfo { transfers.first() }
}
}
}
Expand Down

0 comments on commit 2497eb2

Please sign in to comment.