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
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 = 252
val buildVersion = 253
applicationId = "com.crisiscleanup"
versionCode = buildVersion
versionName = "0.9.${buildVersion - 168}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import com.crisiscleanup.feature.caseeditor.navigation.navigateToCaseAddFlag
import com.crisiscleanup.feature.caseeditor.navigation.navigateToCaseEditor
import com.crisiscleanup.feature.caseeditor.navigation.navigateToTransferWorkType
import com.crisiscleanup.feature.caseeditor.navigation.navigateToViewCase
import com.crisiscleanup.feature.caseeditor.navigation.rerouteToCaseChange
import com.crisiscleanup.feature.caseeditor.navigation.rerouteToViewCase
import com.crisiscleanup.feature.cases.navigation.casesFilterScreen
import com.crisiscleanup.feature.cases.navigation.casesGraph
import com.crisiscleanup.feature.cases.navigation.casesSearchScreen
Expand Down Expand Up @@ -133,7 +133,7 @@ fun CrisisCleanupNavHost(
}
}

val replaceRouteViewCase = navController::rerouteToCaseChange
val replaceRouteViewCase = navController::rerouteToViewCase

val openViewCase = remember(navController) {
{ ids: ExistingWorksiteIdentifier ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ class AndroidFeatureConventionPlugin : Plugin<Project> {
add("implementation", project(":core:common"))
add("implementation", project(":core:data"))
add("implementation", project(":core:designsystem"))
add("implementation", project(":core:domain"))
add("implementation", project(":core:model"))
add("implementation", project(":core:ui"))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinTopLevelExtension

internal const val DefaultConfigTargetSdk = 34
internal const val DefaultConfigTargetSdk = 35

/**
* Configure base Kotlin with Android options
Expand Down
1 change: 0 additions & 1 deletion core/app-component/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ dependencies {
implementation(projects.core.commoncase)
implementation(projects.core.data)
implementation(projects.core.designsystem)
implementation(projects.core.domain)
implementation(projects.core.selectincident)

implementation(libs.androidx.core.ktx)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import com.crisiscleanup.core.data.IncidentSelector
import com.crisiscleanup.core.data.repository.AccountDataRepository
import com.crisiscleanup.core.data.repository.IncidentCacheRepository
import com.crisiscleanup.core.data.repository.IncidentsRepository
import com.crisiscleanup.core.data.repository.LocalAppPreferencesRepository
import com.crisiscleanup.core.domain.LoadSelectIncidents
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.map
Expand All @@ -21,18 +19,9 @@ class AppTopBarDataProvider(
incidentSelector: IncidentSelector,
private val translator: KeyResourceTranslator,
accountDataRepository: AccountDataRepository,
appPreferencesRepository: LocalAppPreferencesRepository,
coroutineScope: CoroutineScope,
) {

val loadSelectIncidents = LoadSelectIncidents(
incidentsRepository = incidentsRepository,
accountDataRepository = accountDataRepository,
incidentSelector = incidentSelector,
appPreferencesRepository = appPreferencesRepository,
coroutineScope = coroutineScope,
)
val incidentsData = loadSelectIncidents.data
val incidentsData = incidentSelector.data

val disasterIconResId = incidentSelector.incident.map { getDisasterIcon(it.disaster) }
.stateIn(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ fun AppTopBar(
modifier: Modifier = Modifier,
incidentDropdownModifier: Modifier = Modifier,
accountToggleModifier: Modifier = Modifier,
incidentSelectTestTag: String = "appIncidentSelect",
dataProvider: AppTopBarDataProvider,
openAuthentication: () -> Unit = {},
onOpenIncidents: (() -> Unit)? = null,
Expand All @@ -35,7 +36,11 @@ fun AppTopBar(

AppTopBar(
modifier = modifier,
incidentDropdownModifier = incidentDropdownModifier,
incidentDropdownModifier = if (enableIncidentSelect) {
incidentDropdownModifier.testTag(incidentSelectTestTag)
} else {
incidentDropdownModifier
},
accountToggleModifier = accountToggleModifier,
title = screenTitle,
isAppHeaderLoading = isHeaderLoading,
Expand Down Expand Up @@ -83,7 +88,7 @@ internal fun AppTopBar(
TruncatedAppBarText(title = title)
} else {
IncidentDropdownSelect(
modifier = incidentDropdownModifier.testTag("appIncidentSelector"),
modifier = incidentDropdownModifier,
onOpenIncidents,
disasterIconResId,
title = title,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class AndroidAppVersionProvider @Inject constructor(

override val version: Pair<Long, String> by lazy {
val code = packageInfo.longVersionCode
val name = packageInfo.versionName
val name = packageInfo.versionName!!
Pair(code, name)
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package com.crisiscleanup.core.data

import com.crisiscleanup.core.common.di.ApplicationScope
import com.crisiscleanup.core.common.subscribedReplay
import com.crisiscleanup.core.data.repository.AccountDataRepository
import com.crisiscleanup.core.data.repository.IncidentsRepository
import com.crisiscleanup.core.data.repository.LocalAppPreferencesRepository
import com.crisiscleanup.core.model.data.EmptyIncident
import com.crisiscleanup.core.model.data.Incident
import com.crisiscleanup.core.model.data.IncidentsData
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import javax.inject.Inject
import javax.inject.Singleton

interface IncidentSelector {
val incidentId: StateFlow<Long>

val incident: StateFlow<Incident>

val data: StateFlow<IncidentsData>

fun selectIncident(incident: Incident)
suspend fun submitIncidentChange(incident: Incident): Boolean
}

@Singleton
class IncidentSelectManager @Inject constructor(
incidentsRepository: IncidentsRepository,
accountDataRepository: AccountDataRepository,
private val appPreferencesRepository: LocalAppPreferencesRepository,
@ApplicationScope private val coroutineScope: CoroutineScope,
) : IncidentSelector {
private val incidentsSource = combine(
incidentsRepository.incidents,
accountDataRepository.accountData,
::Pair,
)
.mapLatest { (incidents, accountData) ->
if (accountData.isCrisisCleanupAdmin) {
incidents
} else {
incidents.filter { accountData.approvedIncidents.contains(it.id) }
}
}

private val preferencesIncidentId =
appPreferencesRepository.userPreferences.map {
it.selectedIncidentId
}

private val selectedIncident = combine(
preferencesIncidentId,
incidentsSource,
::Pair,
)
.map { (selectedId, incidents) ->
incidents.firstOrNull { it.id == selectedId }
?: incidents.firstOrNull()
?: EmptyIncident
}

override val data = combine(
incidentsSource,
selectedIncident,
::Pair,
)
.map { (incidents, selected) ->
if (incidents.isEmpty()) {
IncidentsData.Empty
} else {
IncidentsData.Incidents(incidents, selected)
}
}.stateIn(
scope = coroutineScope,
initialValue = IncidentsData.Loading,
started = subscribedReplay(),
)

override var incident = data.mapNotNull {
(it as? IncidentsData.Incidents)?.selected
}
.stateIn(
scope = coroutineScope,
initialValue = EmptyIncident,
started = subscribedReplay(),
)

override val incidentId = incident.map { it.id }
.stateIn(
scope = coroutineScope,
initialValue = EmptyIncident.id,
started = subscribedReplay(),
)

init {
combine(
preferencesIncidentId,
incidentsSource,
::Pair,
)
.onEach { (selectedId, incidents) ->
val selectedIncident = incidents.find { it.id == selectedId } ?: EmptyIncident
if (selectedIncident == EmptyIncident && incidents.isNotEmpty()) {
val firstIncident = incidents[0]
appPreferencesRepository.setSelectedIncident(firstIncident.id)
}
}
.launchIn(coroutineScope)
}

override fun selectIncident(incident: Incident) {
coroutineScope.launch {
submitIncidentChange(incident)
}
}

override suspend fun submitIncidentChange(incident: Incident): Boolean {
val incidentId = incident.id
val incidents = incidentsSource.first()
incidents
.find { it.id == incidentId }
?.let {
appPreferencesRepository.setSelectedIncident(incidentId)
return true
}

return false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import com.crisiscleanup.core.common.KeyTranslator
import com.crisiscleanup.core.common.NetworkMonitor
import com.crisiscleanup.core.data.AppIncidentMapTracker
import com.crisiscleanup.core.data.IncidentMapTracker
import com.crisiscleanup.core.data.IncidentSelectManager
import com.crisiscleanup.core.data.IncidentSelector
import com.crisiscleanup.core.data.repository.AccountDataRepository
import com.crisiscleanup.core.data.repository.AccountUpdateRepository
import com.crisiscleanup.core.data.repository.AppDataManagementRepository
Expand Down Expand Up @@ -70,6 +72,10 @@ interface DataModule {
networkMonitor: ConnectivityManagerNetworkMonitor,
): NetworkMonitor

@Singleton
@Binds
fun bindsIncidentSelector(selector: IncidentSelectManager): IncidentSelector

@Singleton
@Binds
fun bindsLocalAppPreferencesRepository(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ fun NetworkFile.asEntity() = NetworkFileEntity(
fileTypeT = fileTypeT,
fullUrl = fullUrl,
largeThumbnailUrl = largeThumbnailUrl,
mimeContentType = mimeContentType,
mimeContentType = mimeContentType ?: "",
smallThumbnailUrl = smallThumbnailUrl,
tag = tag,
title = title,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ fun NetworkWorksiteFull.asEntity() = WorksiteEntity(
svi = svi,
what3Words = what3words,
updatedAt = updatedAt,
photoCount = files.map(NetworkFile::mimeContentType)
.filter { it?.startsWith("image/") == true }
.size,
)

// Copy similar changes from [NetworkWorksiteFull.asEntity] above
Expand Down Expand Up @@ -74,6 +77,7 @@ fun NetworkWorksiteCoreData.asEntity() = WorksiteEntity(
svi = svi,
what3Words = what3words,
updatedAt = updatedAt,
photoCount = null,
)

fun NetworkWorksiteShort.asEntity() = WorksiteEntity(
Expand Down Expand Up @@ -105,6 +109,7 @@ fun NetworkWorksiteShort.asEntity() = WorksiteEntity(
plusCode = null,
reportedBy = null,
what3Words = null,
photoCount = null,
)

fun NetworkWorksitePage.asEntity() = WorksiteEntity(
Expand Down Expand Up @@ -136,6 +141,7 @@ fun NetworkWorksitePage.asEntity() = WorksiteEntity(
plusCode = plusCode,
reportedBy = reportedBy,
what3Words = what3words,
photoCount = photoCount,
)

fun KeyDynamicValuePair.asWorksiteEntity() = WorksiteFormDataEntity(
Expand Down
Loading
Loading