Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app-sandbox/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ dependencies {
implementation(libs.androidx.profileinstaller)

implementation(libs.coil.kt)
implementation(libs.coil.kt.compose)

implementation(libs.kotlinx.coroutines.playservices)
implementation(libs.playservices.maps)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ import androidx.navigation.NavController
import com.crisiscleanup.core.designsystem.component.CrisisCleanupBackground
import com.crisiscleanup.core.designsystem.component.CrisisCleanupTextButton
import com.crisiscleanup.core.designsystem.theme.listItemSpacedBy
import com.crisiscleanup.sandbox.navigation.MULTI_IMAGE_ROUTE
import com.crisiscleanup.sandbox.navigation.ASYNC_IMAGE_ROUTE
import com.crisiscleanup.sandbox.navigation.SandboxNavHost
import com.crisiscleanup.sandbox.navigation.navigateToAsyncImage
import com.crisiscleanup.sandbox.navigation.navigateToBottomNav
import com.crisiscleanup.sandbox.navigation.navigateToCheckboxes
import com.crisiscleanup.sandbox.navigation.navigateToChips
Expand Down Expand Up @@ -65,7 +66,7 @@ fun SandboxApp(
SandboxNavHost(
appState.navController,
appState::onBack,
MULTI_IMAGE_ROUTE,
ASYNC_IMAGE_ROUTE,
)
}
}
Expand Down Expand Up @@ -98,6 +99,9 @@ fun RootRoute(navController: NavController) {
CrisisCleanupTextButton(text = "Images") {
navController.navigateToMultiImage()
}
CrisisCleanupTextButton(text = "Async image") {
navController.navigateToAsyncImage()
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,6 @@ class AppSyncer @Inject constructor() : SyncPuller, SyncPusher {

override suspend fun syncPushWorksitesAsync() = CompletableDeferred(SyncResult.NotAttempted(""))

override fun stopPushWorksites() {}

override suspend fun syncPushMedia() = SyncResult.NotAttempted("")

override suspend fun syncPushWorksites() = SyncResult.NotAttempted("")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import com.crisiscleanup.sandbox.RootRoute
import com.crisiscleanup.sandbox.ui.AsyncImageView
import com.crisiscleanup.sandbox.ui.BottomNavRoute
import com.crisiscleanup.sandbox.ui.CheckboxesRoute
import com.crisiscleanup.sandbox.ui.ChipsRoute
Expand All @@ -18,6 +19,7 @@ private const val CHIPS_ROUTE = "chips"
private const val BOTTOM_NAV_ROUTE = "bottom-nav"
const val SINGLE_IMAGE_ROUTE = "single-image"
const val MULTI_IMAGE_ROUTE = "multi-image"
const val ASYNC_IMAGE_ROUTE = "async-image"

fun NavController.navigateToBottomNav() {
this.navigate(BOTTOM_NAV_ROUTE)
Expand All @@ -39,6 +41,10 @@ fun NavController.navigateToMultiImage() {
this.navigate(MULTI_IMAGE_ROUTE)
}

fun NavController.navigateToAsyncImage() {
this.navigate(ASYNC_IMAGE_ROUTE)
}

@Composable
fun SandboxNavHost(
navController: NavHostController,
Expand Down Expand Up @@ -72,5 +78,9 @@ fun SandboxNavHost(
composable(MULTI_IMAGE_ROUTE) {
MultiImageRoute(onBack)
}

composable(ASYNC_IMAGE_ROUTE) {
AsyncImageView()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.crisiscleanup.sandbox.ui

import android.util.Log
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import coil.request.ImageRequest
import com.crisiscleanup.core.common.R
import com.crisiscleanup.core.designsystem.icon.CrisisCleanupIcons

@Composable
fun AsyncImageView() {
val imageUrl = ""
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(imageUrl)
.setHeader("User-Agent", "Mozilla/5.0")
.build(),
modifier = Modifier
.sizeIn(minWidth = 96.dp)
.fillMaxSize()
.clip(RoundedCornerShape(8.dp)),
placeholder = painterResource(R.drawable.cc_grayscale_pin),
error = rememberVectorPainter(CrisisCleanupIcons.SyncProblem),
fallback = rememberVectorPainter(CrisisCleanupIcons.Image),
contentDescription = null,
contentScale = ContentScale.Fit,
onLoading = { loading ->
Log.i("async-image", "Loading image $loading")
},
onSuccess = { success ->
Log.i("async-image", "Successfully loaded ${success.result}")
},
onError = { e ->
Log.e(
"async-image",
"Error loading image ${e.result} for $imageUrl",
e.result.throwable,
)
},
)
}
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ plugins {

android {
defaultConfig {
val buildVersion = 247
val buildVersion = 250
applicationId = "com.crisiscleanup"
versionCode = buildVersion
versionName = "0.9.${buildVersion - 168}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ class MainActivityViewModel @Inject constructor(

incidentSelector.incidentId
.filter { it != EmptyIncident.id }
.distinctUntilChanged()
.onEach {
sync(
forcePullIncidents = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class AppTopBarDataProvider(

val showHeaderLoading = incidentCacheRepository.isSyncingActiveIncident

val enableIncidentSelect = incidentsRepository.isFirstLoad.map(Boolean::not)

val screenTitle = incidentSelector.incident
.map { it.shortName.ifBlank { translator(screenTitleKey) } }
.stateIn(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ fun AppTopBar(
val isHeaderLoading by dataProvider.showHeaderLoading.collectAsState(false)

val disasterIconResId by dataProvider.disasterIconResId.collectAsStateWithLifecycle()
val enableIncidentSelect by dataProvider.enableIncidentSelect.collectAsState(false)

val isAccountExpired by dataProvider.isAccountExpired.collectAsStateWithLifecycle()
val profilePictureUri by dataProvider.profilePictureUri.collectAsStateWithLifecycle()
Expand All @@ -42,6 +43,7 @@ fun AppTopBar(
isAccountExpired = isAccountExpired,
openAuthentication = openAuthentication,
disasterIconResId = disasterIconResId,
enableIncidentSelect = enableIncidentSelect,
onOpenIncidents = onOpenIncidents,
)
}
Expand All @@ -60,6 +62,7 @@ internal fun AppTopBar(
isAccountExpired: Boolean = false,
openAuthentication: () -> Unit = {},
@DrawableRes disasterIconResId: Int = 0,
enableIncidentSelect: Boolean = false,
onOpenIncidents: (() -> Unit)? = null,
) {
val t = LocalAppTranslator.current
Expand All @@ -86,6 +89,7 @@ internal fun AppTopBar(
title = title,
contentDescription = t("nav.change_incident"),
isLoading = isAppHeaderLoading,
enabled = enableIncidentSelect,
)
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ interface SyncPuller {
interface SyncPusher {
fun appPushWorksite(worksiteId: Long, scheduleMediaSync: Boolean = false)
suspend fun syncPushWorksitesAsync(): Deferred<SyncResult>
fun stopPushWorksites()
suspend fun syncPushMedia(): SyncResult
suspend fun syncPushWorksites(): SyncResult

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ class IncidentDataDownloadSpeedMonitor @Inject constructor() : DataDownloadSpeed
override val isSlowSpeed = isSlowSpeedInternal.distinctUntilChanged()

override fun onSpeedChange(isSlow: Boolean) {
this.isSlowSpeedInternal.tryEmit(isSlow)
isSlowSpeedInternal.tryEmit(isSlow)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,6 @@ internal class IncidentDataPullStatsUpdater(
reportChange(pullStats.copy(savedCount = pullStats.savedCount + count))
}

fun clearStep() {
reportChange(
pullStats.copy(
currentStep = 0,
stepTotal = 0,
),
)
}

fun setStep(current: Int, total: Int) {
reportChange(
pullStats.copy(
Expand All @@ -82,6 +73,10 @@ internal class IncidentDataPullStatsUpdater(
)
}

fun clearStep() {
setStep(0, 0)
}

fun setNotificationMessage(message: String = "") {
reportChange(pullStats.copy(notificationMessage = message))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,18 @@ class IncidentOrganizationsSyncer @Inject constructor(
private val appVersionProvider: AppVersionProvider,
@Logger(CrisisCleanupLoggers.Incidents) private val logger: AppLogger,
) : OrganizationsSyncer {
private val organizationFields = listOf(
"id",
"name",
"affiliates",
"is_active",
"primary_location",
"secondary_location",
"type_t",
"primary_contacts",
)

override suspend fun sync(incidentId: Long) {
// TODO Update stats during pull
saveOrganizationsData(incidentId)
}

Expand All @@ -44,11 +54,12 @@ class IncidentOrganizationsSyncer @Inject constructor(

var requestedCount = 0
var networkDataOffset = 0
val pageDataCount = 200
val pageDataCount = 100
try {
while (networkDataOffset < syncCount) {
val worksitesRequest = networkDataSource.getIncidentOrganizations(
incidentId,
organizationFields,
pageDataCount,
networkDataOffset,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ package com.crisiscleanup.core.data.model
import com.crisiscleanup.core.model.data.EmptyIncident
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlin.math.roundToLong
import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.seconds

enum class IncidentPullDataType {
WorksitesCore,
Expand Down Expand Up @@ -63,17 +60,4 @@ data class IncidentDataPullStats(
startProgressAmount
}
}

val projectedFinish: Instant
get() {
val now = Clock.System.now()
val delta = now - startTime
val p = progress
if (p <= 0 || delta <= 0.seconds) {
return now.plus(999_999.hours)
}

val projectedDeltaSeconds = (delta.inWholeSeconds / p).roundToLong().seconds
return startTime.plus(projectedDeltaSeconds)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ data class IncidentDataSyncParameters(

fun isSignificantChange(
other: BoundedRegion,
thresholdMiles: Float = 0.5f,
thresholdMiles: Double = 0.5,
): Boolean {
// ~69 miles in 1 degree. 1/69 ~= 0.0145 (degrees).
val thresholdDegrees = 0.0145 * thresholdMiles
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json

fun IncidentDataSyncParametersEntity.asExternalModel(logger: AppLogger): IncidentDataSyncParameters {
val boundedRegion = if (boundedRegion.isNotBlank()) {
val savedRegion = if (boundedRegion.isNotBlank()) {
try {
Json.decodeFromString<IncidentDataSyncParameters.BoundedRegion>(boundedRegion)
} catch (e: Exception) {
Expand All @@ -28,7 +28,7 @@ fun IncidentDataSyncParametersEntity.asExternalModel(logger: AppLogger): Inciden
after = additionalUpdatedAfter,
),
),
boundedRegion = boundedRegion,
boundedRegion = savedRegion,
boundedSyncedAt = boundedSyncedAt,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,7 @@ class CrisisCleanupDataManagementRepository @Inject constructor(

private suspend fun isSyncPullStopped(): Boolean {
val cacheStage = incidentCacheRepository.cacheStage.first()
return setOf(
IncidentCacheStage.Start,
IncidentCacheStage.End,
).contains(cacheStage)
return !cacheStage.isSyncingStage
}

private suspend fun clearPersistedAppData() {
Expand Down
Loading
Loading