Skip to content

Commit

Permalink
Merge branch 'master' into sufy/2131/offline-auth
Browse files Browse the repository at this point in the history
  • Loading branch information
gino-m authored Mar 5, 2024
2 parents d6eb1b4 + 26f2447 commit ca5c2d1
Show file tree
Hide file tree
Showing 29 changed files with 254 additions and 403 deletions.
1 change: 0 additions & 1 deletion .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 9 additions & 8 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ buildscript {
ext {
// As of Gradle 8.5, Kotlin plugin only tested up to 1.9.20.
kotlinVersion = "1.9.20"
hiltVersion = "2.50"
navigationVersion = "2.5.3"
hiltVersion = "2.51"
navigationVersion = "2.7.7"
roomVersion = "2.6.1"
}
repositories {
Expand All @@ -35,15 +35,15 @@ buildscript {
}
dependencies {
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$navigationVersion"
classpath 'com.android.tools.build:gradle:8.2.0'
classpath 'com.google.gms:google-services:4.3.15'
classpath 'com.android.tools.build:gradle:8.2.2'
classpath 'com.google.gms:google-services:4.4.1'
classpath "com.pascalwelsch.gitversioner:gitversioner:0.5.0"

// Performance Monitoring plugin: https://firebase.google.com/docs/perf-mon
classpath 'com.google.firebase:perf-plugin:1.4.2'

// Crashlytics plugin
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.5'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.9'

// Kotlin
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
Expand All @@ -55,7 +55,7 @@ buildscript {
}

plugins {
id "com.github.ben-manes.versions" version "0.36.0"
id "com.github.ben-manes.versions" version "0.51.0"
id "org.jetbrains.kotlin.android" version "$kotlinVersion" apply false
id "org.jetbrains.kotlin.plugin.serialization" version "$kotlinVersion"
id "com.ncorti.ktfmt.gradle" version "0.17.0"
Expand Down Expand Up @@ -111,6 +111,9 @@ gitVersioner {
baseBranch "master"
}

// https://github.com/ben-manes/gradle-versions-plugin/issues/746
apply plugin: 'jvm-ecosystem'

def isNonStable = { String version ->
def stableKeyword = ['RELEASE', 'FINAL', 'GA'].any { it -> version.toUpperCase().contains(it) }
def regex = /^[0-9,.v-]+(-r)?$/
Expand Down Expand Up @@ -138,7 +141,5 @@ ext {
androidCompileSdk = 34
androidMinSdk = 24
androidTargetSdk = 33

gmsMapsVersion = '18.1.0'
jvmToolchainVersion = 17
}
14 changes: 8 additions & 6 deletions cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,9 @@ steps:
./gradlew -PdisablePreDex testDevStagingUnitTest --no-daemon 2> unit-test-logs.txt || echo "fail" > build-status.txt
cat unit-test-logs.txt
# TODO: Add a check for _PUSH_TO_MASTER
./gradlew jacocoTestStagingUnitTestReport --no-daemon
if [[ "${_PUSH_TO_MASTER}" ]]; then
./gradlew jacocoTestStagingUnitTestReport --no-daemon
fi
- name: 'gcr.io/$PROJECT_ID/android:34'
id: &authenticate_gcloud 'Authorize gcloud'
Expand Down Expand Up @@ -219,10 +220,11 @@ steps:
args:
- '-c'
- |
# TODO: Add a check for _PUSH_TO_MASTER
curl -Os https://uploader.codecov.io/latest/linux/codecov
chmod +x codecov
./codecov -t ${_CODECOV_TOKEN}
if [[ "${_PUSH_TO_MASTER}" ]]; then
curl -Os https://uploader.codecov.io/latest/linux/codecov
chmod +x codecov
./codecov -t ${_CODECOV_TOKEN}
fi
- name: 'gcr.io/$PROJECT_ID/android:base'
id: &compress_cache 'Compress gradle build cache'
Expand Down
47 changes: 21 additions & 26 deletions ground/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,12 @@ apply from: '../config/lint/lint.gradle'
apply from: '../config/jacoco/jacoco.gradle'

project.ext {
autoDisposeVersion = "1.4.0"
autoValueVersion = "1.9"
autoValueVersion = "1.10.4"
fragmentVersion = "1.5.7"
hiltJetpackVersion = "1.0.0"
lifecycleVersion = "2.6.1"
workVersion = "2.8.1"
mockitoVersion = "4.5.1"
mockitoKotlinVersion = "4.1.0"
hiltJetpackVersion = "1.2.0"
lifecycleVersion = "2.7.0"
workVersion = "2.9.0"
mockitoVersion = "5.11.0"
coroutinesVersion = "1.6.4"
}

Expand Down Expand Up @@ -167,13 +165,13 @@ dependencies {
androidTestImplementation project(':sharedTest')

implementation 'androidx.multidex:multidex:2.0.1'
implementation 'androidx.preference:preference-ktx:1.2.0'
implementation 'androidx.preference:preference-ktx:1.2.1'

// Kotlin
implementation "org.jetbrains.kotlin:kotlin-stdlib:$project.kotlinVersion"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.0-RC"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.4.0-RC"
implementation "org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.5"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.6.3"
implementation "org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.7"

// Kotlin Coroutines
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion"
Expand All @@ -188,25 +186,25 @@ dependencies {
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.compose.ui:ui:1.6.1'
implementation 'androidx.compose.compiler:compiler:1.5.9'
implementation 'androidx.compose.ui:ui:1.6.2'
implementation 'androidx.compose.compiler:compiler:1.5.10'
implementation 'androidx.compose.material3:material3-android:1.2.0'

// Google Play Services.
implementation 'com.google.android.gms:play-services-auth:20.6.0'
implementation "com.google.android.gms:play-services-maps:$rootProject.gmsMapsVersion"
implementation 'com.google.android.gms:play-services-location:21.0.1'
implementation 'com.google.android.gms:play-services-auth:21.0.0'
implementation 'com.google.android.gms:play-services-maps:18.2.0'
implementation 'com.google.android.gms:play-services-location:21.1.0'

implementation "com.google.maps.android:android-maps-utils:2.3.0"
implementation "com.google.maps.android:android-maps-utils:3.8.2"

// GeoJSON support
implementation 'com.google.code.gson:gson:2.10'
implementation 'com.google.code.gson:gson:2.10.1'

// Test Json
testImplementation 'org.json:json:20180813'

// Firebase and related libraries.
implementation platform('com.google.firebase:firebase-bom:32.4.1')
implementation platform('com.google.firebase:firebase-bom:32.7.3')
implementation 'com.google.firebase:firebase-analytics'
implementation 'com.google.firebase:firebase-firestore'
implementation 'com.google.firebase:firebase-functions-ktx'
Expand Down Expand Up @@ -269,15 +267,12 @@ dependencies {
implementation "androidx.work:work-runtime-ktx:$workVersion"
testImplementation "androidx.work:work-testing:$workVersion"

implementation "com.uber.autodispose:autodispose-android:$project.autoDisposeVersion"
implementation "com.uber.autodispose:autodispose-android-archcomponents:$project.autoDisposeVersion"

// Testing
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
testImplementation 'com.google.truth:truth:1.1.3'
androidTestImplementation 'com.google.truth:truth:1.1.3'
testImplementation 'com.google.truth:truth:1.4.2'
androidTestImplementation 'com.google.truth:truth:1.4.2'
testImplementation 'androidx.test:core:1.5.0'
testImplementation 'org.robolectric:robolectric:4.11.1'
testImplementation 'android.arch.core:core-testing:1.1.1'
Expand All @@ -290,12 +285,12 @@ dependencies {
testImplementation 'app.cash.turbine:turbine:0.12.3'

// Mockito
testImplementation "org.mockito:mockito-inline:$mockitoVersion"
testImplementation 'org.mockito:mockito-inline:4.5.1'
testImplementation "org.mockito:mockito-core:$mockitoVersion"
testImplementation "org.mockito:mockito-android:$mockitoVersion"
androidTestImplementation "org.mockito:mockito-core:$mockitoVersion"
androidTestImplementation "org.mockito:mockito-android:$mockitoVersion"
testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
testImplementation 'org.mockito.kotlin:mockito-kotlin:4.1.0'

// Espresso
testImplementation 'androidx.test.espresso:espresso-contrib:3.5.1'
Expand Down
3 changes: 2 additions & 1 deletion ground/src/main/java/com/google/android/ground/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,11 @@ object Config {
const val MAX_MEDIA_UPLOAD_RETRY_COUNT = 5

// TODO(#1730): Make sub-paths configurable and stop hardcoding here.
const val DEFAULT_MOG_TILE_LOCATION = "/offline-imagery/default"
const val DEFAULT_MOG_MIN_ZOOM = 8
const val DEFAULT_MOG_MAX_ZOOM = 14

fun getMogSources(path: String = "/offline-imagery/default/") =
fun getMogSources(path: String) =
listOf(
MogSource(
0 ..< DEFAULT_MOG_MIN_ZOOM,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ class GroundApplication : MultiDexApplication(), Configuration.Provider {
@Inject lateinit var crashReportingTree: CrashReportingTree
@Inject lateinit var workerFactory: HiltWorkerFactory

override val workManagerConfiguration: Configuration
get() = Configuration.Builder().setWorkerFactory(workerFactory).build()

private fun isReleaseBuild(): Boolean = BuildConfig.BUILD_TYPE.contentEquals("release")

override fun onCreate() {
Expand All @@ -47,9 +50,6 @@ class GroundApplication : MultiDexApplication(), Configuration.Provider {
}
}

override fun getWorkManagerConfiguration(): Configuration =
Configuration.Builder().setWorkerFactory(workerFactory).build()

private fun setStrictMode() {
// NOTE: Enabling strict thread policy causes Maps SDK to lag on pan and zoom. Enable
// only as needed when debugging.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ data class Survey(
val title: String,
val description: String,
val jobMap: Map<String, Job>,
// TODO(#1730): Remove tileSources from survey.
val tileSources: List<TileSource> = listOf(),
val acl: Map<String, String> = mapOf()
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
package com.google.android.ground.model.locationofinterest

import com.google.android.ground.model.AuditInfo
import com.google.android.ground.model.geometry.*
import com.google.android.ground.model.geometry.Geometry
import com.google.android.ground.model.job.Job
import com.google.android.ground.model.mutation.LocationOfInterestMutation
import com.google.android.ground.model.mutation.Mutation
Expand Down Expand Up @@ -75,6 +75,8 @@ data class LocationOfInterest(
submissionCount = submissionCount,
ownerEmail = ownerEmail,
isOpportunistic = isOpportunistic,
properties = properties
properties = properties,
)

fun getProperty(key: String): String = properties[key]?.toString() ?: ""
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ constructor(
private suspend fun getLocalTileSourcePath(): String = File(fileUtil.getFilesDir(), "tiles").path

fun getOfflineTileSourcesFlow() =
surveyRepository.activeSurveyFlow.combine(getOfflineAreaBounds()) { survey, bounds ->
applyBounds(survey?.tileSources, bounds)
surveyRepository.activeSurveyFlow.combine(getOfflineAreaBounds()) { _, bounds ->
applyBounds(getDefaultTileSources(), bounds)
}

private suspend fun applyBounds(
Expand Down Expand Up @@ -143,15 +143,14 @@ constructor(
return MogClient(mogCollection, remoteStorageManager)
}

private fun getMogSources(): List<MogSource> = Config.getMogSources(getFirstTileSourceUrl())
private fun getMogSources(): List<MogSource> =
Config.getMogSources(getDefaultTileSources().first().url)

/**
* Returns the URL of the first tile source in the current survey, or throws an error if no survey
* is active or if no tile sources are defined.
*/
private fun getFirstTileSourceUrl() =
surveyRepository.activeSurvey?.tileSources?.firstOrNull()?.url
?: error("Survey has no tile sources")
/** Returns the default configured tile sources. */
fun getDefaultTileSources(): List<TileSource> =
listOf(
TileSource(url = Config.DEFAULT_MOG_TILE_LOCATION, type = TileSource.Type.MOG_COLLECTION)
)

suspend fun hasHiResImagery(bounds: Bounds): Boolean {
val client = getMogClient()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,46 +17,48 @@ package com.google.android.ground.ui.common

import android.content.res.Resources
import com.google.android.ground.R
import com.google.android.ground.model.AuditInfo
import com.google.android.ground.model.User
import com.google.android.ground.model.geometry.LineString
import com.google.android.ground.model.geometry.LinearRing
import com.google.android.ground.model.geometry.Geometry
import com.google.android.ground.model.geometry.MultiPolygon
import com.google.android.ground.model.geometry.Point
import com.google.android.ground.model.geometry.Polygon
import com.google.android.ground.model.locationofinterest.LocationOfInterest
import java.util.Optional
import javax.inject.Inject

/** Common logic for formatting attributes of [LocationOfInterest] for display to the user. */
/** Helper class for creating user-visible text. */
class LocationOfInterestHelper @Inject internal constructor(private val resources: Resources) {
fun getCreatedBy(locationOfInterest: Optional<LocationOfInterest>): String =
getUserName(locationOfInterest).map { resources.getString(R.string.added_by, it) }.orElse("")

// TODO(#793): Allow user-defined LOI names for other LOI types.
fun getLabel(locationOfInterest: Optional<LocationOfInterest>): String =
locationOfInterest.map(::getLabel).orElse("")
fun getDisplayLoiName(loi: LocationOfInterest): String {
val loiId = loi.customId.ifEmpty { loi.getProperty("id") }
val loiName = loi.getProperty("name")

fun getLabel(loi: LocationOfInterest): String {
// TODO(#2046): Reuse logic from card util to display LOI label
val caption = loi.customId?.trim { it <= ' ' } ?: ""
return caption.ifEmpty { getLocationOfInterestType(loi) }
return when {
loiName.isNotEmpty() && loiId.isNotEmpty() -> "$loiName ($loiId)"
loiName.isNotEmpty() -> loiName
loiId.isNotEmpty() -> "${loi.geometry.toType()} ($loiId)"
else -> loi.geometry.toDefaultName()
}
}

private fun getLocationOfInterestType(locationOfInterest: LocationOfInterest): String =
when (locationOfInterest.geometry) {
is Polygon -> "Polygon"
is Point -> "Point"
is LineString -> "LineString"
is LinearRing -> "LinearRing"
is MultiPolygon -> "MultiPolygon"
fun getJobName(loi: LocationOfInterest): String? = loi.job.name

/** Returns a user-visible string representing the type of the geometry. */
private fun Geometry.toType(): String =
when (this) {
is Point -> resources.getString(R.string.point)
is Polygon,
is MultiPolygon -> resources.getString(R.string.area)
else -> throw IllegalArgumentException("Unsupported geometry type $this")
}

fun getSubtitle(locationOfInterest: Optional<LocationOfInterest>): String =
locationOfInterest
.map { resources.getString(R.string.layer_label_format, it.job.name) }
.orElse("")
/** Returns a default user-visible name for the geometry. */
private fun Geometry.toDefaultName(): String =
when (this) {
is Point -> resources.getString(R.string.unnamed_point)
is Polygon,
is MultiPolygon -> resources.getString(R.string.unnamed_area)
else -> throw IllegalArgumentException("Unsupported geometry type $this")
}

private fun getUserName(locationOfInterest: Optional<LocationOfInterest>): Optional<String> =
locationOfInterest.map(LocationOfInterest::created).map(AuditInfo::user).map(User::displayName)
fun getSubtitle(loi: LocationOfInterest): String =
resources.getString(R.string.layer_label_format, loi.job.name)
}
Loading

0 comments on commit ca5c2d1

Please sign in to comment.