Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
06557e77b8 | ||
|
|
a08fe31d3d |
@@ -13,8 +13,8 @@ android {
|
|||||||
applicationId = "pl.firmatpp.kierowca"
|
applicationId = "pl.firmatpp.kierowca"
|
||||||
minSdk = 26
|
minSdk = 26
|
||||||
targetSdk = 35
|
targetSdk = 35
|
||||||
versionCode = 15
|
versionCode = 17
|
||||||
versionName = "1.0.14"
|
versionName = "1.0.16"
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
buildConfigField("String", "API_BASE_URL", "\"https://api-intranet.firmatpp.pl/api/\"")
|
buildConfigField("String", "API_BASE_URL", "\"https://api-intranet.firmatpp.pl/api/\"")
|
||||||
|
|||||||
@@ -69,6 +69,13 @@ class PhotoUploadOutbox(
|
|||||||
enqueueWorker(clientRequestId)
|
enqueueWorker(clientRequestId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun discard(clientRequestId: String) {
|
||||||
|
dao.find(clientRequestId)?.let { upload ->
|
||||||
|
File(upload.localPath).delete()
|
||||||
|
dao.delete(upload.clientRequestId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun discardConfirmedServerPhotos(route: DriverRouteDto) {
|
suspend fun discardConfirmedServerPhotos(route: DriverRouteDto) {
|
||||||
val confirmedRequestIds = route.photos.mapNotNull { it.clientRequestId }.distinct()
|
val confirmedRequestIds = route.photos.mapNotNull { it.clientRequestId }.distinct()
|
||||||
if (confirmedRequestIds.isEmpty()) return
|
if (confirmedRequestIds.isEmpty()) return
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ import androidx.compose.material.ExperimentalMaterialApi
|
|||||||
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
||||||
import androidx.compose.material.pullrefresh.pullRefresh
|
import androidx.compose.material.pullrefresh.pullRefresh
|
||||||
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
||||||
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ButtonDefaults
|
import androidx.compose.material3.ButtonDefaults
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
@@ -75,6 +76,7 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -177,7 +179,16 @@ fun DriverApp(viewModel: DriverViewModel) {
|
|||||||
onRoute = viewModel::openRoute,
|
onRoute = viewModel::openRoute,
|
||||||
)
|
)
|
||||||
DriverScreen.Profile -> ProfileScreen(state, viewModel::refreshRoutes, viewModel::openProfile, viewModel::logout)
|
DriverScreen.Profile -> ProfileScreen(state, viewModel::refreshRoutes, viewModel::openProfile, viewModel::logout)
|
||||||
DriverScreen.Detail -> DetailScreen(state, viewModel::back, viewModel::uploadPhoto, viewModel::openPhoto, viewModel::deletePhoto, viewModel::retryPhotoUpload, viewModel::refreshSelectedRoute)
|
DriverScreen.Detail -> DetailScreen(
|
||||||
|
state,
|
||||||
|
viewModel::back,
|
||||||
|
viewModel::uploadPhoto,
|
||||||
|
viewModel::openPhoto,
|
||||||
|
viewModel::deletePhoto,
|
||||||
|
viewModel::deleteConfirmedUpload,
|
||||||
|
viewModel::retryPhotoUpload,
|
||||||
|
viewModel::refreshSelectedRoute,
|
||||||
|
)
|
||||||
DriverScreen.Photo -> PhotoScreen(state, viewModel::back)
|
DriverScreen.Photo -> PhotoScreen(state, viewModel::back)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -736,6 +747,7 @@ private fun DetailScreen(
|
|||||||
onUpload: (Uri, String, PhotoUploadMetadata) -> Unit,
|
onUpload: (Uri, String, PhotoUploadMetadata) -> Unit,
|
||||||
onPhoto: (RoutePhotoDto) -> Unit,
|
onPhoto: (RoutePhotoDto) -> Unit,
|
||||||
onDeletePhoto: (RoutePhotoDto) -> Unit,
|
onDeletePhoto: (RoutePhotoDto) -> Unit,
|
||||||
|
onDeleteUpload: (PhotoUploadEntity) -> Unit,
|
||||||
onRetryUpload: (PhotoUploadEntity) -> Unit,
|
onRetryUpload: (PhotoUploadEntity) -> Unit,
|
||||||
onRefresh: () -> Unit,
|
onRefresh: () -> Unit,
|
||||||
) {
|
) {
|
||||||
@@ -782,6 +794,7 @@ private fun DetailScreen(
|
|||||||
canManagePhotos = canManagePhotos,
|
canManagePhotos = canManagePhotos,
|
||||||
onPhoto = onPhoto,
|
onPhoto = onPhoto,
|
||||||
onDeletePhoto = onDeletePhoto,
|
onDeletePhoto = onDeletePhoto,
|
||||||
|
onDeleteUpload = onDeleteUpload,
|
||||||
onRetryUpload = onRetryUpload,
|
onRetryUpload = onRetryUpload,
|
||||||
onCamera = {
|
onCamera = {
|
||||||
val newUri = createCameraUri(context)
|
val newUri = createCameraUri(context)
|
||||||
@@ -973,6 +986,7 @@ private fun CargoDocumentationSection(
|
|||||||
canManagePhotos: Boolean,
|
canManagePhotos: Boolean,
|
||||||
onPhoto: (RoutePhotoDto) -> Unit,
|
onPhoto: (RoutePhotoDto) -> Unit,
|
||||||
onDeletePhoto: (RoutePhotoDto) -> Unit,
|
onDeletePhoto: (RoutePhotoDto) -> Unit,
|
||||||
|
onDeleteUpload: (PhotoUploadEntity) -> Unit,
|
||||||
onRetryUpload: (PhotoUploadEntity) -> Unit,
|
onRetryUpload: (PhotoUploadEntity) -> Unit,
|
||||||
onCamera: () -> Unit,
|
onCamera: () -> Unit,
|
||||||
onGallery: () -> Unit,
|
onGallery: () -> Unit,
|
||||||
@@ -995,7 +1009,7 @@ private fun CargoDocumentationSection(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PhotoGrid(photos, uploads, deletingPhotoIds, imageAuthHeader, onPhoto, onDeletePhoto, onRetryUpload)
|
PhotoGrid(photos, uploads, deletingPhotoIds, imageAuthHeader, onPhoto, onDeletePhoto, onDeleteUpload, onRetryUpload)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1021,9 +1035,13 @@ private fun PhotoGrid(
|
|||||||
imageAuthHeader: String?,
|
imageAuthHeader: String?,
|
||||||
onPhoto: (RoutePhotoDto) -> Unit,
|
onPhoto: (RoutePhotoDto) -> Unit,
|
||||||
onDeletePhoto: (RoutePhotoDto) -> Unit,
|
onDeletePhoto: (RoutePhotoDto) -> Unit,
|
||||||
|
onDeleteUpload: (PhotoUploadEntity) -> Unit,
|
||||||
onRetryUpload: (PhotoUploadEntity) -> Unit,
|
onRetryUpload: (PhotoUploadEntity) -> Unit,
|
||||||
) {
|
) {
|
||||||
val items = uploads.map { PhotoGridItem.Upload(it) } + photos.map { PhotoGridItem.Server(it) }
|
var pendingDelete by remember { mutableStateOf<PhotoDeleteTarget?>(null) }
|
||||||
|
val items = (uploads.map { PhotoGridItem.Upload(it) } + photos.map { PhotoGridItem.Server(it) })
|
||||||
|
.sortedByDescending { it.sortEpochMillis }
|
||||||
|
val visibleAttachmentCount = visiblePhotoAttachmentCount(photos.size, uploads.size)
|
||||||
|
|
||||||
Card(
|
Card(
|
||||||
colors = CardDefaults.cardColors(containerColor = Color.White),
|
colors = CardDefaults.cardColors(containerColor = Color.White),
|
||||||
@@ -1032,7 +1050,7 @@ private fun PhotoGrid(
|
|||||||
) {
|
) {
|
||||||
Column(Modifier.padding(20.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) {
|
Column(Modifier.padding(20.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||||
Text(
|
Text(
|
||||||
"Załączone zdjęcia (${photos.size})",
|
"Załączone zdjęcia ($visibleAttachmentCount)",
|
||||||
color = TppColors.Muted,
|
color = TppColors.Muted,
|
||||||
fontFamily = FontFamily.Monospace,
|
fontFamily = FontFamily.Monospace,
|
||||||
fontWeight = FontWeight.SemiBold,
|
fontWeight = FontWeight.SemiBold,
|
||||||
@@ -1052,11 +1070,13 @@ private fun PhotoGrid(
|
|||||||
imageAuthHeader = imageAuthHeader,
|
imageAuthHeader = imageAuthHeader,
|
||||||
isDeleting = item.photo.id in deletingPhotoIds,
|
isDeleting = item.photo.id in deletingPhotoIds,
|
||||||
onPhoto = onPhoto,
|
onPhoto = onPhoto,
|
||||||
onDeletePhoto = onDeletePhoto,
|
onDeletePhoto = { pendingDelete = PhotoDeleteTarget.Server(it) },
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
)
|
)
|
||||||
is PhotoGridItem.Upload -> PendingPhotoTile(
|
is PhotoGridItem.Upload -> PendingPhotoTile(
|
||||||
upload = item.upload,
|
upload = item.upload,
|
||||||
|
isDeleting = item.upload.serverPhotoId?.let { it in deletingPhotoIds } == true,
|
||||||
|
onDelete = { pendingDelete = PhotoDeleteTarget.Upload(it) },
|
||||||
onRetry = onRetryUpload,
|
onRetry = onRetryUpload,
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
)
|
)
|
||||||
@@ -1071,11 +1091,45 @@ private fun PhotoGrid(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pendingDelete?.let { target ->
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = { pendingDelete = null },
|
||||||
|
title = { Text("Usunąć zdjęcie?", color = TppColors.Ink, fontWeight = FontWeight.Bold) },
|
||||||
|
text = { Text("Czy na pewno chcesz usunąć to zdjęcie?", color = TppColors.Muted) },
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(
|
||||||
|
onClick = {
|
||||||
|
pendingDelete = null
|
||||||
|
when (target) {
|
||||||
|
is PhotoDeleteTarget.Server -> onDeletePhoto(target.photo)
|
||||||
|
is PhotoDeleteTarget.Upload -> onDeleteUpload(target.upload)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
Text("Usuń", color = TppColors.Error, fontWeight = FontWeight.Bold)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissButton = {
|
||||||
|
TextButton(onClick = { pendingDelete = null }) {
|
||||||
|
Text("Anuluj", color = TppColors.Muted)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class PhotoGridItem {
|
private sealed class PhotoGridItem(open val sortEpochMillis: Long) {
|
||||||
data class Server(val photo: RoutePhotoDto) : PhotoGridItem()
|
data class Server(val photo: RoutePhotoDto) : PhotoGridItem(
|
||||||
data class Upload(val upload: PhotoUploadEntity) : PhotoGridItem()
|
routePhotoSortEpochMillis(photo.createdAt, photo.takenAt, fallback = 0L),
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Upload(val upload: PhotoUploadEntity) : PhotoGridItem(upload.createdAtEpochMillis)
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class PhotoDeleteTarget {
|
||||||
|
data class Server(val photo: RoutePhotoDto) : PhotoDeleteTarget()
|
||||||
|
data class Upload(val upload: PhotoUploadEntity) : PhotoDeleteTarget()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -1127,10 +1181,13 @@ private fun PhotoTile(
|
|||||||
@Composable
|
@Composable
|
||||||
private fun PendingPhotoTile(
|
private fun PendingPhotoTile(
|
||||||
upload: PhotoUploadEntity,
|
upload: PhotoUploadEntity,
|
||||||
|
isDeleting: Boolean,
|
||||||
|
onDelete: (PhotoUploadEntity) -> Unit,
|
||||||
onRetry: (PhotoUploadEntity) -> Unit,
|
onRetry: (PhotoUploadEntity) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val status = upload.statusType
|
val status = upload.statusType
|
||||||
|
val canDeleteServerPhoto = confirmedUploadServerPhotoId(upload.status, upload.serverPhotoId) != null
|
||||||
Box(modifier.aspectRatio(1f).background(TppColors.Panel, RoundedCornerShape(4.dp))) {
|
Box(modifier.aspectRatio(1f).background(TppColors.Panel, RoundedCornerShape(4.dp))) {
|
||||||
AsyncImage(
|
AsyncImage(
|
||||||
model = File(upload.localPath),
|
model = File(upload.localPath),
|
||||||
@@ -1139,6 +1196,33 @@ private fun PendingPhotoTile(
|
|||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
)
|
)
|
||||||
Box(Modifier.fillMaxSize().background(Color.Black.copy(alpha = 0.34f)))
|
Box(Modifier.fillMaxSize().background(Color.Black.copy(alpha = 0.34f)))
|
||||||
|
if (isDeleting) {
|
||||||
|
Box(
|
||||||
|
Modifier.fillMaxSize().background(Color.White.copy(alpha = 0.72f)),
|
||||||
|
contentAlignment = Alignment.Center,
|
||||||
|
) {
|
||||||
|
Text("Usuwam", color = TppColors.Muted, fontFamily = FontFamily.Monospace, fontWeight = FontWeight.Bold)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (canDeleteServerPhoto) {
|
||||||
|
IconButton(
|
||||||
|
onClick = { onDelete(upload) },
|
||||||
|
enabled = !isDeleting,
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.TopEnd)
|
||||||
|
.padding(8.dp)
|
||||||
|
.size(40.dp)
|
||||||
|
.background(TppColors.Surface.copy(alpha = 0.96f), RoundedCornerShape(20.dp))
|
||||||
|
.border(1.dp, TppColors.Error.copy(alpha = 0.35f), RoundedCornerShape(20.dp)),
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
Icons.Outlined.Delete,
|
||||||
|
contentDescription = "Usuń zdjęcie",
|
||||||
|
tint = TppColors.Error,
|
||||||
|
modifier = Modifier.size(19.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Column(
|
Column(
|
||||||
Modifier.align(Alignment.BottomStart).fillMaxWidth().background(Color.White.copy(alpha = 0.94f)).padding(10.dp),
|
Modifier.align(Alignment.BottomStart).fillMaxWidth().background(Color.White.copy(alpha = 0.94f)).padding(10.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
|
|||||||
@@ -1,9 +1,26 @@
|
|||||||
package pl.firmatpp.kierowca.ui
|
package pl.firmatpp.kierowca.ui
|
||||||
|
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
|
import java.time.OffsetDateTime
|
||||||
|
|
||||||
fun canManageRoutePhotos(selectedDate: String, today: LocalDate = LocalDate.now()): Boolean =
|
fun canManageRoutePhotos(selectedDate: String, today: LocalDate = LocalDate.now()): Boolean =
|
||||||
runCatching { LocalDate.parse(selectedDate).isEqual(today) }.getOrDefault(false)
|
runCatching { LocalDate.parse(selectedDate).isEqual(today) }.getOrDefault(false)
|
||||||
|
|
||||||
fun inlinePhotoGridRows(photoCount: Int): Int =
|
fun inlinePhotoGridRows(photoCount: Int): Int =
|
||||||
if (photoCount <= 0) 0 else (photoCount + 1) / 2
|
if (photoCount <= 0) 0 else (photoCount + 1) / 2
|
||||||
|
|
||||||
|
fun visiblePhotoAttachmentCount(serverPhotoCount: Int, localUploadCount: Int): Int =
|
||||||
|
serverPhotoCount.coerceAtLeast(0) + localUploadCount.coerceAtLeast(0)
|
||||||
|
|
||||||
|
fun routePhotoSortEpochMillis(createdAt: String?, takenAt: String?, fallback: Long): Long =
|
||||||
|
parseIsoOffsetEpochMillis(createdAt)
|
||||||
|
?: parseIsoOffsetEpochMillis(takenAt)
|
||||||
|
?: fallback
|
||||||
|
|
||||||
|
fun confirmedUploadServerPhotoId(status: String, serverPhotoId: String?): String? =
|
||||||
|
serverPhotoId?.takeIf { status == "CONFIRMED" && it.isNotBlank() }
|
||||||
|
|
||||||
|
private fun parseIsoOffsetEpochMillis(value: String?): Long? =
|
||||||
|
value?.takeIf { it.isNotBlank() }?.let {
|
||||||
|
runCatching { OffsetDateTime.parse(it).toInstant().toEpochMilli() }.getOrNull()
|
||||||
|
}
|
||||||
|
|||||||
@@ -210,6 +210,31 @@ class DriverViewModel(application: Application) : AndroidViewModel(application)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun deleteConfirmedUpload(upload: PhotoUploadEntity) {
|
||||||
|
val route = _state.value.selectedRoute ?: return
|
||||||
|
val serverPhotoId = confirmedUploadServerPhotoId(upload.status, upload.serverPhotoId) ?: return
|
||||||
|
|
||||||
|
viewModelScope.launch {
|
||||||
|
_state.update { it.copy(deletingPhotoIds = it.deletingPhotoIds + serverPhotoId, error = null) }
|
||||||
|
runCatching {
|
||||||
|
repository.deletePhoto(serverPhotoId)
|
||||||
|
photoUploadOutbox.discard(upload.clientRequestId)
|
||||||
|
val response = repository.route(route.id)
|
||||||
|
photoUploadOutbox.discardConfirmedServerPhotos(response.route)
|
||||||
|
_state.update {
|
||||||
|
it.copy(
|
||||||
|
selectedRoute = response.route,
|
||||||
|
routes = it.routes.map { item -> if (item.id == route.id) response.route else item },
|
||||||
|
error = null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}.onFailure { throwable ->
|
||||||
|
_state.update { it.copy(error = ApiErrorMapper.map(throwable).message) }
|
||||||
|
}
|
||||||
|
_state.update { it.copy(deletingPhotoIds = it.deletingPhotoIds - serverPhotoId) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun openPhoto(photo: RoutePhotoDto) {
|
fun openPhoto(photo: RoutePhotoDto) {
|
||||||
_state.update { it.copy(screen = DriverScreen.Photo, selectedPhoto = photo) }
|
_state.update { it.copy(screen = DriverScreen.Photo, selectedPhoto = photo) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,4 +30,42 @@ class DriverUiRulesTest {
|
|||||||
assertEquals(2, inlinePhotoGridRows(3))
|
assertEquals(2, inlinePhotoGridRows(3))
|
||||||
assertEquals(3, inlinePhotoGridRows(5))
|
assertEquals(3, inlinePhotoGridRows(5))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun countsServerPhotosAndLocalUploadsAsVisibleAttachments() {
|
||||||
|
assertEquals(0, visiblePhotoAttachmentCount(serverPhotoCount = 0, localUploadCount = 0))
|
||||||
|
assertEquals(1, visiblePhotoAttachmentCount(serverPhotoCount = 0, localUploadCount = 1))
|
||||||
|
assertEquals(3, visiblePhotoAttachmentCount(serverPhotoCount = 1, localUploadCount = 2))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun usesCreatedAtBeforeTakenAtForNewestFirstPhotoSorting() {
|
||||||
|
val fallback = 100L
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
1_782_892_800_000L,
|
||||||
|
routePhotoSortEpochMillis(
|
||||||
|
createdAt = "2026-07-01T10:00:00+02:00",
|
||||||
|
takenAt = "2026-07-01T08:00:00+02:00",
|
||||||
|
fallback = fallback,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
1_782_885_600_000L,
|
||||||
|
routePhotoSortEpochMillis(
|
||||||
|
createdAt = null,
|
||||||
|
takenAt = "2026-07-01T08:00:00+02:00",
|
||||||
|
fallback = fallback,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
assertEquals(fallback, routePhotoSortEpochMillis(createdAt = null, takenAt = null, fallback = fallback))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun allowsDeleteIconForConfirmedLocalUploadWithServerPhotoId() {
|
||||||
|
assertEquals("42", confirmedUploadServerPhotoId("CONFIRMED", "42"))
|
||||||
|
assertEquals(null, confirmedUploadServerPhotoId("CONFIRMED", ""))
|
||||||
|
assertEquals(null, confirmedUploadServerPhotoId("UPLOADING", "42"))
|
||||||
|
assertEquals(null, confirmedUploadServerPhotoId("FAILED_RETRYABLE", "42"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user