diff --git a/config/detekt/detekt.yml b/config/detekt/detekt.yml index 481da8d551..5020fc7d3c 100644 --- a/config/detekt/detekt.yml +++ b/config/detekt/detekt.yml @@ -590,9 +590,9 @@ style: value: 'FIXME:' - reason: 'Forbidden STOPSHIP todo marker in comment, please address the problem before shipping the code.' value: 'STOPSHIP:' - # - reason: 'Forbidden TODO todo marker in comment, please do the changes.' - # value: 'TODO:' - allowedPatterns: '' + - reason: 'TODO comment format should be: // TODO: $description' + value: '// TODO:' + allowedPatterns: '^//\s*TODO:\s+.+$' ForbiddenImport: active: false imports: [ ] diff --git a/ground/build.gradle b/ground/build.gradle index 771594ca2a..a4d925b6a6 100644 --- a/ground/build.gradle +++ b/ground/build.gradle @@ -79,7 +79,8 @@ android { minSdkVersion rootProject.androidMinSdk targetSdkVersion rootProject.androidTargetSdk - // TODO(https://github.com/google/ground-android/pull/985): Calculate version code manually + // TODO: Calculate version code manually + // Issue URL: https://github.com/google/ground-android/pull/985 versionCode gitVersioner.versionCode versionName gitVersioner.versionName + " " + getCommitSha1() testInstrumentationRunner "com.google.android.ground.CustomTestRunner" @@ -358,7 +359,8 @@ dependencies { implementation "com.google.guava:guava:33.0.0-android" - // TODO(#1748): Move protos into shared module and set correct path here. + // TODO: Move protos into shared module and set correct path here. + // Issue URL: https://github.com/google/ground-android/issues/1748 api("com.google.protobuf:protobuf-kotlin-lite:4.26.1") // Pulls protodefs from the specified commit in the ground-platform repo. diff --git a/ground/src/main/java/com/google/android/ground/Config.kt b/ground/src/main/java/com/google/android/ground/Config.kt index c2ccefa522..baeea07dfb 100644 --- a/ground/src/main/java/com/google/android/ground/Config.kt +++ b/ground/src/main/java/com/google/android/ground/Config.kt @@ -44,7 +44,9 @@ object Config { */ const val CLUSTERING_ZOOM_THRESHOLD = 14f - // TODO(#1730): Make sub-paths configurable and stop hardcoding here. + // TODO: Make sub-paths configurable and + // stop hardcoding here. + // Issue URL: https://github.com/google/ground-android/issues/1730 const val DEFAULT_MOG_TILE_LOCATION = "/offline-imagery/default" private const val DEFAULT_MOG_MIN_ZOOM = 8 private const val DEFAULT_MOG_MAX_ZOOM = 14 diff --git a/ground/src/main/java/com/google/android/ground/MainActivity.kt b/ground/src/main/java/com/google/android/ground/MainActivity.kt index d085ad4460..882361e47e 100644 --- a/ground/src/main/java/com/google/android/ground/MainActivity.kt +++ b/ground/src/main/java/com/google/android/ground/MainActivity.kt @@ -63,7 +63,8 @@ class MainActivity : AbstractActivity() { override fun onCreate(savedInstanceState: Bundle?) { // Make sure this is before calling super.onCreate() setTheme(R.style.AppTheme) - // TODO(#620): Remove this to enable dark theme. + // TODO: Remove this to enable dark theme. + // Issue URL: https://github.com/google/ground-android/issues/620 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) super.onCreate(savedInstanceState) @@ -122,7 +123,9 @@ class MainActivity : AbstractActivity() { var showDialog by remember { mutableStateOf(true) } if (showDialog) { PermissionDeniedDialog( - // TODO(#2402): Read url from Firestore config/properties/signUpUrl + // TODO: Read url from + // Firestore config/properties/signUpUrl + // Issue URL: https://github.com/google/ground-android/issues/2402 BuildConfig.SIGNUP_FORM_LINK, onSignOut = { showDialog = false diff --git a/ground/src/main/java/com/google/android/ground/MainViewModel.kt b/ground/src/main/java/com/google/android/ground/MainViewModel.kt index aa696d8cfe..7513830d18 100644 --- a/ground/src/main/java/com/google/android/ground/MainViewModel.kt +++ b/ground/src/main/java/com/google/android/ground/MainViewModel.kt @@ -64,6 +64,7 @@ constructor( init { viewModelScope.launch { // TODO: Check auth status whenever fragments resumes + // Issue URL: https://github.com/google/ground-android/issues/2624 authenticationManager.signInState.collect { _navigationRequests.emit(onSignInStateChange(it)) } @@ -86,7 +87,8 @@ constructor( Timber.d("User cancelled sign in") MainUiState.OnUserSignedOut } else { - // TODO(#1808): Display some error dialog to the user with a helpful user-readable message. + // TODO: Display some error dialog to the user with a helpful user-readable message. + // Issue URL: https://github.com/google/ground-android/issues/1808 onUserSignedOut() } } @@ -100,9 +102,10 @@ constructor( surveyRepository.clearActiveSurvey() userRepository.clearUserPreferences() - // TODO(#1691): Once multi-user login is supported, avoid clearing local db data. This is + // TODO: Once multi-user login is supported, avoid clearing local db data. This is // currently being done to prevent one user's data to be submitted as another user after // re-login. + // Issue URL: https://github.com/google/ground-android/issues/1691 viewModelScope.launch { withContext(ioDispatcher) { localDatabase.clearAllTables() } } return MainUiState.OnUserSignedOut } diff --git a/ground/src/main/java/com/google/android/ground/model/geometry/Geometry.kt b/ground/src/main/java/com/google/android/ground/model/geometry/Geometry.kt index ab0b2ba6ab..5756aeb681 100644 --- a/ground/src/main/java/com/google/android/ground/model/geometry/Geometry.kt +++ b/ground/src/main/java/com/google/android/ground/model/geometry/Geometry.kt @@ -123,7 +123,8 @@ data class LinearRing(val coordinates: List) : Geometry { override fun isEmpty() = coordinates.isEmpty() override fun validate() { - // TODO(#1647): Check for vertices count > 3 + // TODO: Check for vertices count > 3 + // Issue URL: https://github.com/google/ground-android/issues/1647 if (coordinates.isEmpty()) { return } diff --git a/ground/src/main/java/com/google/android/ground/model/job/Job.kt b/ground/src/main/java/com/google/android/ground/model/job/Job.kt index 1e341bbc4a..55b70a7ccd 100644 --- a/ground/src/main/java/com/google/android/ground/model/job/Job.kt +++ b/ground/src/main/java/com/google/android/ground/model/job/Job.kt @@ -41,8 +41,8 @@ data class Job( val tasksSorted: List get() = tasks.values.sortedBy { it.index } - // TODO(#2216): Consider using nulls to indicate absence of value here instead of throwing - // an exception. + // TODO: Consider using nulls to indicate absence of value here instead of throwing an exception. + // Issue URL: https://github.com/google/ground-android/issues/2216 fun getTask(id: String): Task = tasks[id] ?: throw TaskNotFoundException(id) /** Job must contain at-most 1 `AddLoiTask`. */ diff --git a/ground/src/main/java/com/google/android/ground/model/locationofinterest/LocationOfInterest.kt b/ground/src/main/java/com/google/android/ground/model/locationofinterest/LocationOfInterest.kt index ff374df5bb..7cb23d5189 100644 --- a/ground/src/main/java/com/google/android/ground/model/locationofinterest/LocationOfInterest.kt +++ b/ground/src/main/java/com/google/android/ground/model/locationofinterest/LocationOfInterest.kt @@ -59,6 +59,7 @@ data class LocationOfInterest( * database. */ // TODO: Remove this test-only method + // Issue URL: https://github.com/google/ground-android/issues/2903 fun toMutation(type: Mutation.Type, userId: String): LocationOfInterestMutation = LocationOfInterestMutation( jobId = job.id, diff --git a/ground/src/main/java/com/google/android/ground/model/submission/CaptureLocationTaskData.kt b/ground/src/main/java/com/google/android/ground/model/submission/CaptureLocationTaskData.kt index a288a42d61..5ac0a40e7e 100644 --- a/ground/src/main/java/com/google/android/ground/model/submission/CaptureLocationTaskData.kt +++ b/ground/src/main/java/com/google/android/ground/model/submission/CaptureLocationTaskData.kt @@ -30,6 +30,7 @@ data class CaptureLocationTaskData( ) : GeometryTaskData(location) { override fun getDetailsText(): String { // TODO: Move to strings.xml for i18n + // Issue URL: https://github.com/google/ground-android/issues/1733 val df = DecimalFormat("#.##") df.roundingMode = RoundingMode.DOWN val coordinatesString = location.coordinates.toDmsFormat() diff --git a/ground/src/main/java/com/google/android/ground/model/submission/DropPinTaskData.kt b/ground/src/main/java/com/google/android/ground/model/submission/DropPinTaskData.kt index 48580efc1d..b187f482a7 100644 --- a/ground/src/main/java/com/google/android/ground/model/submission/DropPinTaskData.kt +++ b/ground/src/main/java/com/google/android/ground/model/submission/DropPinTaskData.kt @@ -23,7 +23,8 @@ import java.text.DecimalFormat /** User-provided response to a "drop a pin" data collection [Task]. */ data class DropPinTaskData(val location: Point) : GeometryTaskData(location) { override fun getDetailsText(): String { - // TODO(#752): Move to strings.xml for i18n + // TODO: Move to strings.xml for i18n + // Issue URL: https://github.com/google/ground-android/issues/752 val df = DecimalFormat("#.##") df.roundingMode = RoundingMode.DOWN return location.coordinates.toDmsFormat() ?: "" diff --git a/ground/src/main/java/com/google/android/ground/model/submission/GeometryTaskData.kt b/ground/src/main/java/com/google/android/ground/model/submission/GeometryTaskData.kt index 86fcbc2536..a571288495 100644 --- a/ground/src/main/java/com/google/android/ground/model/submission/GeometryTaskData.kt +++ b/ground/src/main/java/com/google/android/ground/model/submission/GeometryTaskData.kt @@ -25,7 +25,8 @@ import com.google.android.ground.model.geometry.Polygon /** A user-provided response to a geometry-based task ("drop a pin" or "draw an area"). */ abstract class GeometryTaskData(val geometry: Geometry) : TaskData { - // TODO(#1733): Move strings to view layer. + // TODO: Move strings to view layer. + // Issue URL: https://github.com/google/ground-android/issues/1733 override fun getDetailsText(): String = when (geometry) { is Point -> "Point data" diff --git a/ground/src/main/java/com/google/android/ground/model/submission/MultipleChoiceTaskData.kt b/ground/src/main/java/com/google/android/ground/model/submission/MultipleChoiceTaskData.kt index 21b6790c9f..4bf2d42c97 100644 --- a/ground/src/main/java/com/google/android/ground/model/submission/MultipleChoiceTaskData.kt +++ b/ground/src/main/java/com/google/android/ground/model/submission/MultipleChoiceTaskData.kt @@ -40,7 +40,6 @@ class MultipleChoiceTaskData( suffix = MultipleChoiceTaskViewModel.OTHER_SUFFIX, ) ?: "" - // TODO: Make these inner classes non-static and access Task directly. override fun getDetailsText(): String = selectedOptionIds .mapNotNull { multipleChoice?.getOptionById(it) } diff --git a/ground/src/main/java/com/google/android/ground/model/submission/SubmissionData.kt b/ground/src/main/java/com/google/android/ground/model/submission/SubmissionData.kt index 00da379010..407ea1f98d 100644 --- a/ground/src/main/java/com/google/android/ground/model/submission/SubmissionData.kt +++ b/ground/src/main/java/com/google/android/ground/model/submission/SubmissionData.kt @@ -21,7 +21,6 @@ package com.google.android.ground.model.submission * @property data A map from task id to values. This map is mutable and therefore should never be * exposed outside this class. */ -// TODO: Merge into Submission? data class SubmissionData(private val data: Map = mapOf()) { /** diff --git a/ground/src/main/java/com/google/android/ground/model/task/Task.kt b/ground/src/main/java/com/google/android/ground/model/task/Task.kt index 26b423501b..7526bb6a35 100644 --- a/ground/src/main/java/com/google/android/ground/model/task/Task.kt +++ b/ground/src/main/java/com/google/android/ground/model/task/Task.kt @@ -35,10 +35,9 @@ constructor( val condition: Condition? = null, ) { - /** - * Task type names as they appear in the remote db, but in uppercase. DO NOT RENAME! TODO: Define - * these in data layer! - */ + // TODO: Define these in data layer! + // Issue URL: https://github.com/google/ground-android/issues/2910 + // Task type names as they appear in the local db, but in uppercase. DO NOT RENAME! enum class Type { UNKNOWN, TEXT, diff --git a/ground/src/main/java/com/google/android/ground/persistence/local/room/converter/ConverterExt.kt b/ground/src/main/java/com/google/android/ground/persistence/local/room/converter/ConverterExt.kt index 9f5704f9d5..9e89e1c9f1 100644 --- a/ground/src/main/java/com/google/android/ground/persistence/local/room/converter/ConverterExt.kt +++ b/ground/src/main/java/com/google/android/ground/persistence/local/room/converter/ConverterExt.kt @@ -171,7 +171,8 @@ fun LocationOfInterestMutation.toLocalDataStoreObject(user: User): LocationOfInt surveyId = surveyId, jobId = jobId, deletionState = EntityDeletionState.DEFAULT, - // TODO(#1562): Preserve creation audit info for UPDATE mutations. + // TODO: Preserve creation audit info for UPDATE mutations. + // Issue URL: https://github.com/google/ground-android/issues/1562 created = auditInfo, lastModified = auditInfo, geometry = geometry?.toLocalDataStoreObject(), @@ -321,7 +322,8 @@ fun SubmissionMutation.toLocalDataStoreObject(created: AuditInfo): SubmissionEnt locationOfInterestId = this.locationOfInterestId, deletionState = EntityDeletionState.DEFAULT, data = SubmissionDataConverter.toString(SubmissionData().copyWithDeltas(this.deltas)), - // TODO(#1562): Preserve creation audit info for UPDATE mutations. + // TODO: Preserve creation audit info for UPDATE mutations. + // Issue URL: https://github.com/google/ground-android/issues/1562 created = auditInfo, lastModified = auditInfo, ) diff --git a/ground/src/main/java/com/google/android/ground/persistence/local/room/converter/ValueJsonConverter.kt b/ground/src/main/java/com/google/android/ground/persistence/local/room/converter/ValueJsonConverter.kt index 19cd720edb..9b7a33ac2d 100644 --- a/ground/src/main/java/com/google/android/ground/persistence/local/room/converter/ValueJsonConverter.kt +++ b/ground/src/main/java/com/google/android/ground/persistence/local/room/converter/ValueJsonConverter.kt @@ -61,7 +61,6 @@ internal object ValueJsonConverter { private fun toJsonArray(response: MultipleChoiceTaskData): JSONArray = JSONArray().apply { response.selectedOptionIds.forEach { this.put(it) } } - // TODO: Replace with proto conversion logic if this is still necessary fun toResponse(task: Task, obj: Any): TaskData? { if (JSONObject.NULL === obj) { return null diff --git a/ground/src/main/java/com/google/android/ground/persistence/local/room/entity/UserEntity.kt b/ground/src/main/java/com/google/android/ground/persistence/local/room/entity/UserEntity.kt index 08d904e2de..f22c82b729 100644 --- a/ground/src/main/java/com/google/android/ground/persistence/local/room/entity/UserEntity.kt +++ b/ground/src/main/java/com/google/android/ground/persistence/local/room/entity/UserEntity.kt @@ -24,6 +24,7 @@ data class UserEntity( @ColumnInfo(name = "id") @PrimaryKey val id: String, @ColumnInfo(name = "email") val email: String, @ColumnInfo(name = "display_name") val displayName: String, - // TODO(https://github.com/google/ground-android/issues/964): Save to remote db + // TODO: Save to remote db + // Issue URL: https://github.com/google/ground-android/issues/964 @ColumnInfo(name = "photo_url") val photoUrl: String?, ) diff --git a/ground/src/main/java/com/google/android/ground/persistence/local/room/fields/MutationEntitySyncStatus.kt b/ground/src/main/java/com/google/android/ground/persistence/local/room/fields/MutationEntitySyncStatus.kt index a7ba61f78a..d4033e2d9d 100644 --- a/ground/src/main/java/com/google/android/ground/persistence/local/room/fields/MutationEntitySyncStatus.kt +++ b/ground/src/main/java/com/google/android/ground/persistence/local/room/fields/MutationEntitySyncStatus.kt @@ -24,8 +24,9 @@ import com.google.android.ground.persistence.local.room.IntEnum.Companion.toInt /** Mutually exclusive mutations states. */ enum class MutationEntitySyncStatus(private val intValue: Int, private val enumValue: SyncStatus) : IntEnum { - // TODO(#950): Set IN_PROGRESS and FAILED statuses when necessary. On failure, set retry count and - // error and update to PENDING. + // TODO: Set IN_PROGRESS and FAILED statuses + // when necessary. On failure, set retry count and error and update to PENDING. + // Issue URL: https://github.com/google/ground-android/issues/950 UNKNOWN(0, SyncStatus.UNKNOWN), /** Pending includes failed sync attempts pending retry. */ diff --git a/ground/src/main/java/com/google/android/ground/persistence/local/room/stores/RoomLocationOfInterestStore.kt b/ground/src/main/java/com/google/android/ground/persistence/local/room/stores/RoomLocationOfInterestStore.kt index 06ca236aac..a68e784a7d 100644 --- a/ground/src/main/java/com/google/android/ground/persistence/local/room/stores/RoomLocationOfInterestStore.kt +++ b/ground/src/main/java/com/google/android/ground/persistence/local/room/stores/RoomLocationOfInterestStore.kt @@ -55,7 +55,8 @@ class RoomLocationOfInterestStore @Inject internal constructor() : LocalLocation ): LocationOfInterest? = locationOfInterestDao.findById(locationOfInterestId)?.toModelObject(survey) - // TODO(#706): Apply pending local mutations before saving. + // TODO: Apply pending local mutations before saving. + // Issue URL: https://github.com/google/ground-android/issues/706 override suspend fun merge(model: LocationOfInterest) { locationOfInterestDao.insertOrUpdate(model.toLocalDataStoreObject()) } diff --git a/ground/src/main/java/com/google/android/ground/persistence/remote/DataStoreException.kt b/ground/src/main/java/com/google/android/ground/persistence/remote/DataStoreException.kt index d9e6cbe5b5..25fa3f2804 100644 --- a/ground/src/main/java/com/google/android/ground/persistence/remote/DataStoreException.kt +++ b/ground/src/main/java/com/google/android/ground/persistence/remote/DataStoreException.kt @@ -29,7 +29,8 @@ open class DataStoreException(message: String?) : RuntimeException(message) { @JvmStatic @Throws(DataStoreException::class) fun checkType(expectedType: Class<*>, obj: T): T { - // TODO(#2743) - Handle Kotlin Long (java.lang.Long) vs Java primitive long (long) + // TODO: Handle Kotlin Long (java.lang.Long) vs Java primitive long (long) + // Issue URL: https://github.com/google/ground-android/issues/2743 if (obj.javaClass == java.lang.Long::class.java && expectedType == Long::class.java) { return obj } diff --git a/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/FirebaseStorageManager.kt b/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/FirebaseStorageManager.kt index 147817b28b..6c5fbde02f 100644 --- a/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/FirebaseStorageManager.kt +++ b/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/FirebaseStorageManager.kt @@ -26,8 +26,6 @@ import kotlinx.coroutines.CancellationException import kotlinx.coroutines.tasks.await import timber.log.Timber -// TODO: Add column to Submission table for storing uploaded media urls -// TODO: Synced to remote db as well @Singleton class FirebaseStorageManager @Inject constructor() : RemoteStorageManager { @@ -61,7 +59,6 @@ class FirebaseStorageManager @Inject constructor() : RemoteStorageManager { * * user-media/surveys/{survey_id}/submissions/{field_id-uuid.jpg} */ - // TODO: Refactor this into MediaStorageRepository. fun getRemoteMediaPath(surveyId: String, filename: String): String = StringJoiner(File.separator) .add(MEDIA_ROOT_DIR) diff --git a/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/FirestoreDataStore.kt b/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/FirestoreDataStore.kt index 4bf14c31ce..0b178a63b0 100644 --- a/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/FirestoreDataStore.kt +++ b/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/FirestoreDataStore.kt @@ -64,7 +64,8 @@ internal constructor( override fun getSurveyList(user: User): Flow> = flow { emitAll( db().surveys().getReadable(user).map { list -> - // TODO(#2031): Return SurveyListItem from getReadable(), only fetch required fields. + // TODO: Return SurveyListItem from getReadable(), only fetch required fields. + // Issue URL: https://github.com/google/ground-android/issues/2031 list.map { it.toListItem(false) } } ) diff --git a/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/base/FluentFirestore.kt b/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/base/FluentFirestore.kt index 3692bee225..c7a639e5ae 100644 --- a/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/base/FluentFirestore.kt +++ b/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/base/FluentFirestore.kt @@ -24,6 +24,5 @@ open class FluentFirestore protected constructor(private val db: FirebaseFiresto protected fun db(): FirebaseFirestore = db - // TODO: Wrap in fluent version of WriteBatch. fun batch(): WriteBatch = db.batch() } diff --git a/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/protobuf/FirestoreToProtobufExt.kt b/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/protobuf/FirestoreToProtobufExt.kt index f2150f57f4..d9e04601de 100644 --- a/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/protobuf/FirestoreToProtobufExt.kt +++ b/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/protobuf/FirestoreToProtobufExt.kt @@ -144,5 +144,6 @@ private fun FirestoreValue.toMessageValue(targetType: KClass<*>): MessageValue = ?: throw IllegalArgumentException("Unrecognized enum number $this") } else { throw UnsupportedOperationException("Unsupported message field type $targetType") - // TODO(#1748): Handle arrays, GeoPoint, int, and other types. + // TODO: Handle arrays, GeoPoint, int, and other types. + // Issue URL: https://github.com/google/ground-android/issues/1748 } diff --git a/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/protobuf/ModelToProtoExt.kt b/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/protobuf/ModelToProtoExt.kt index 620750efed..48acc0b5d8 100644 --- a/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/protobuf/ModelToProtoExt.kt +++ b/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/protobuf/ModelToProtoExt.kt @@ -60,7 +60,6 @@ import com.google.protobuf.timestamp import java.util.Date import kotlinx.collections.immutable.toImmutableMap -// TODO: Add test coverage fun SubmissionMutation.createSubmissionMessage(user: User) = submission { assert(userId == user.id) { "UserId doesn't match: expected $userId, found ${user.id}" } @@ -127,7 +126,6 @@ fun LocationOfInterestMutation.createLoiMessage(user: User) = locationOfInterest } private fun toTaskData(id: String, newTaskData: TaskData) = taskData { - // TODO: What should be the ID? taskId = id when (newTaskData) { @@ -147,7 +145,6 @@ private fun toTaskData(id: String, newTaskData: TaskData) = taskData { newTaskData.altitude?.let { altitude = it } newTaskData.accuracy?.let { accuracy = it } coordinates = newTaskData.location.coordinates.toMessage() - // TODO: Add timestamp } is GeometryTaskData -> drawGeometryResult = drawGeometryResult { geometry = newTaskData.geometry.toMessage() diff --git a/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/protobuf/ProtobufToFirestoreExt.kt b/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/protobuf/ProtobufToFirestoreExt.kt index d95b3aacc4..ca13cbe5f1 100644 --- a/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/protobuf/ProtobufToFirestoreExt.kt +++ b/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/protobuf/ProtobufToFirestoreExt.kt @@ -67,7 +67,8 @@ private fun Message.hasValue(property: KProperty<*>): Boolean { } private fun MessageValue.toFirestoreValue(): FirestoreValue = - // TODO(#1748): Convert enums and other types. + // TODO: Convert enums and other types. + // Issue URL: https://github.com/google/ground-android/issues/1748 when (this) { is List<*> -> map { it?.toFirestoreValue() } is Message -> toFirestoreMap() diff --git a/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/schema/LoiCollectionReference.kt b/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/schema/LoiCollectionReference.kt index f2cb4e5c12..1284cbf27c 100644 --- a/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/schema/LoiCollectionReference.kt +++ b/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/schema/LoiCollectionReference.kt @@ -43,7 +43,8 @@ class LoiCollectionReference internal constructor(ref: CollectionReference) : /** Retrieves all "predefined" LOIs in the specified survey. Main-safe. */ suspend fun fetchPredefined(survey: Survey): List = // Use !=false rather than ==true to not break legacy dev surveys. - // TODO(#2375): Switch to whereEqualTo(true) once legacy dev surveys deleted or migrated. + // TODO: Switch to whereEqualTo(true) once legacy dev surveys deleted or migrated. + // Issue URL: https://github.com/google/ground-android/issues/2375 fetchLois( survey, reference().whereEqualTo(SOURCE_FIELD, LocationOfInterestProto.Source.IMPORTED.number), diff --git a/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/schema/LoiConverter.kt b/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/schema/LoiConverter.kt index a6da3fc0a0..7be2b442b2 100644 --- a/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/schema/LoiConverter.kt +++ b/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/schema/LoiConverter.kt @@ -24,10 +24,10 @@ import com.google.android.ground.proto.LocationOfInterest as LocationOfInterestP import com.google.android.ground.proto.LocationOfInterest.Source import com.google.firebase.firestore.DocumentSnapshot -// TODO: Add tests. /** Converts between Firestore documents and [LocationOfInterest] instances. */ object LoiConverter { - // TODO(#2392): Define field names on DocumentReference objects, not converters. + // TODO: Define field names on DocumentReference objects, not converters. + // Issue URL: https://github.com/google/ground-android/issues/2375 const val GEOMETRY_TYPE = "type" const val POLYGON_TYPE = "Polygon" @@ -71,7 +71,8 @@ object LoiConverter { job = job, created = created, lastModified = lastModified, - // TODO(#929): Set geometry once LOI has been updated to use our own model. + // TODO: Set geometry once LOI has been updated to use our own model. + // Issue URL: https://github.com/google/ground-android/issues/929 geometry = geometry, submissionCount = submissionCount, properties = properties, diff --git a/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/schema/SurveyDocumentReference.kt b/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/schema/SurveyDocumentReference.kt index 909c2b0a95..18f05d50b7 100644 --- a/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/schema/SurveyDocumentReference.kt +++ b/ground/src/main/java/com/google/android/ground/persistence/remote/firebase/schema/SurveyDocumentReference.kt @@ -39,8 +39,8 @@ class SurveyDocumentReference internal constructor(ref: DocumentReference) : suspend fun get(): Survey? { try { val surveyDoc = reference().get().await() - // TODO(https://github.com/google/ground-android/issues/2864): Move jobs fetch to outside this - // DocumentReference class. + // TODO: Move jobs fetch to outside this DocumentReference class. + // Issue URL: https://github.com/google/ground-android/issues/2864 val jobs = jobs().get() return SurveyConverter.toSurvey(surveyDoc, jobs) } catch (e: CancellationException) { diff --git a/ground/src/main/java/com/google/android/ground/persistence/sync/LocalMutationSyncWorker.kt b/ground/src/main/java/com/google/android/ground/persistence/sync/LocalMutationSyncWorker.kt index ba795443d2..bdab825912 100644 --- a/ground/src/main/java/com/google/android/ground/persistence/sync/LocalMutationSyncWorker.kt +++ b/ground/src/main/java/com/google/android/ground/persistence/sync/LocalMutationSyncWorker.kt @@ -69,8 +69,8 @@ constructor( try { val user = userRepository.getAuthenticatedUser() mutationRepository.markAsInProgress(mutations) - // TODO(https://github.com/google/ground-android/issues/2883): - // Apply mutations via repository layer rather than accessing data store directly. + // TODO: Apply mutations via repository layer rather than accessing data store directly. + // Issue URL: https://github.com/google/ground-android/issues/2883 remoteDataStore.applyMutations(mutations, user) mutationRepository.finalizePendingMutationsForMediaUpload(mutations) diff --git a/ground/src/main/java/com/google/android/ground/persistence/sync/MediaUploadWorker.kt b/ground/src/main/java/com/google/android/ground/persistence/sync/MediaUploadWorker.kt index 1db783ffe0..bdede31ed4 100644 --- a/ground/src/main/java/com/google/android/ground/persistence/sync/MediaUploadWorker.kt +++ b/ground/src/main/java/com/google/android/ground/persistence/sync/MediaUploadWorker.kt @@ -76,8 +76,9 @@ constructor( } else { mutationRepository.markAsFailedMediaUpload( listOf(mutation), - // TODO(https://github.com/google/ground-android/issues/2120): Replace this workaround with - // update of specific [MediaMutation], aggregate to [UploadQueueEntry] for display in UI. + // TODO: Replace this workaround with update of specific [MediaMutation], + // aggregate to [UploadQueueEntry] for display in UI. + // Issue URL: https://github.com/google/ground-android/issues/2120 results.firstNotNullOfOrNull { it.exceptionOrNull() } ?: UnknownError(), ) return false diff --git a/ground/src/main/java/com/google/android/ground/persistence/sync/WorkRequestBuilder.kt b/ground/src/main/java/com/google/android/ground/persistence/sync/WorkRequestBuilder.kt index 10f03e448d..25e41fc18a 100644 --- a/ground/src/main/java/com/google/android/ground/persistence/sync/WorkRequestBuilder.kt +++ b/ground/src/main/java/com/google/android/ground/persistence/sync/WorkRequestBuilder.kt @@ -76,8 +76,9 @@ class WorkRequestBuilder { companion object { /** Backoff time should increase linearly. */ - // TODO(#710): Check if it is possible to wake the worker as soon as the connection becomes + // TODO: Check if it is possible to wake the worker as soon as the connection becomes // available, and if so switch to EXPONENTIAL backoff policy. + // Issue URL: https://github.com/google/ground-android/issues/710 private val BACKOFF_POLICY = BackoffPolicy.LINEAR /** Number of milliseconds to wait before retrying failed sync tasks. */ diff --git a/ground/src/main/java/com/google/android/ground/repository/LocationOfInterestRepository.kt b/ground/src/main/java/com/google/android/ground/repository/LocationOfInterestRepository.kt index f8bed98c5c..48684f070f 100644 --- a/ground/src/main/java/com/google/android/ground/repository/LocationOfInterestRepository.kt +++ b/ground/src/main/java/com/google/android/ground/repository/LocationOfInterestRepository.kt @@ -58,7 +58,8 @@ constructor( ) { /** Mirrors locations of interest in the specified survey from the remote db into the local db. */ suspend fun syncLocationsOfInterest(survey: Survey) { - // TODO(#2384): Allow survey organizers to make ad hoc LOIs visible to all data collectors. + // TODO: Allow survey organizers to make ad hoc LOIs visible to all data collectors. + // Issue URL: https://github.com/google/ground-android/issues/2384 val ownerUserId = authenticationManager.getAuthenticatedUser().id val lois = with(remoteDataStore) { loadPredefinedLois(survey) + loadUserLois(survey, ownerUserId) } diff --git a/ground/src/main/java/com/google/android/ground/repository/MutationRepository.kt b/ground/src/main/java/com/google/android/ground/repository/MutationRepository.kt index 117b95b749..6dbe60eace 100644 --- a/ground/src/main/java/com/google/android/ground/repository/MutationRepository.kt +++ b/ground/src/main/java/com/google/android/ground/repository/MutationRepository.kt @@ -54,11 +54,10 @@ constructor( * subscribe and a new list on each subsequent change. */ fun getSurveyMutationsFlow(survey: Survey): Flow> { - // TODO(https://github.com/google/ground-android/issues/2838): Show mutations for all surveys, - // not just current one. - // TODO(https://github.com/google/ground-android/issues/2838): This method is also named - // incorrectly - it only returns one of LOI or submission mutations. We should delete this - // method in favor of [getUploadQueueFlow()]. + // TODO: Show mutations for all surveys, not just current one. + // TODO: This method is also named incorrectly - it only returns one of LOI or submission + // mutations. We should delete this method in favor of [getUploadQueueFlow()]. + // Issue URL: https://github.com/google/ground-android/issues/2838 val locationOfInterestMutations = localLocationOfInterestStore.getAllSurveyMutations(survey) val submissionMutations = localSubmissionStore.getAllSurveyMutationsFlow(survey) @@ -85,8 +84,8 @@ constructor( setOf(MEDIA_UPLOAD_PENDING, MEDIA_UPLOAD_IN_PROGRESS, MEDIA_UPLOAD_AWAITING_RETRY) .contains(it.uploadStatus) } - // TODO(https://github.com/google/ground-android/issues/2120): - // Return [MediaMutations] instead once introduced. + // TODO: Return [MediaMutations] instead once introduced. + // Issue URL: https://github.com/google/ground-android/issues/2120 .mapNotNull { it.submissionMutation } /** @@ -147,8 +146,8 @@ constructor( */ suspend fun finalizePendingMutationsForMediaUpload(mutations: List) { finalizeDeletions(mutations) - // TODO(https://github.com/google/ground-android/issues/2873): Only do this is there are - // actually photos to upload. + // TODO: Only do this is there are actually photos to upload. + // Issue URL: https://github.com/google/ground-android/issues/2873 markForMediaUpload(mutations) } diff --git a/ground/src/main/java/com/google/android/ground/repository/OfflineAreaRepository.kt b/ground/src/main/java/com/google/android/ground/repository/OfflineAreaRepository.kt index 9870cee8b2..0d2a85f68b 100644 --- a/ground/src/main/java/com/google/android/ground/repository/OfflineAreaRepository.kt +++ b/ground/src/main/java/com/google/android/ground/repository/OfflineAreaRepository.kt @@ -100,7 +100,8 @@ constructor( } } - // TODO(#1730): Generate local tiles path based on source base path. + // TODO: Generate local tiles path based on source base path. + // Issue URL: https://github.com/google/ground-android/issues/1730 private fun getLocalTileSourcePath(): String = File(fileUtil.getFilesDir(), "tiles").path fun getOfflineTileSourcesFlow(): Flow = diff --git a/ground/src/main/java/com/google/android/ground/system/ActivityStreams.kt b/ground/src/main/java/com/google/android/ground/system/ActivityStreams.kt index 9f51b3f024..d8843b669e 100644 --- a/ground/src/main/java/com/google/android/ground/system/ActivityStreams.kt +++ b/ground/src/main/java/com/google/android/ground/system/ActivityStreams.kt @@ -76,21 +76,23 @@ class ActivityStreams @Inject constructor(@ApplicationScope private val scope: C fun getActivityResults(requestCode: Int): Flow = _activityResults.filter { it.requestCode == requestCode } + // TODO: Define and handle timeouts. + // Issue URL: https://github.com/google/ground-android/issues/723 /** * Emits the next [Activity.onActivityResult] event where `requestCode` matches the specified * value. */ suspend fun getNextActivityResult(requestCode: Int): ActivityResult = - getActivityResults(requestCode).first() // TODO(#723): Define and handle timeouts. + getActivityResults(requestCode).first() + // TODO: Define and handle timeouts. + // Issue URL: https://github.com/google/ground-android/issues/723 /** * Emits the next [Activity.onRequestPermissionsResult] event where `requestCode` matches the * specified value. */ suspend fun getNextRequestPermissionsResult(requestCode: Int): RequestPermissionsResult = - _requestPermissionsResults - .filter { it.requestCode == requestCode } - .first() // TODO(#723): Define and handle timeouts. + _requestPermissionsResults.filter { it.requestCode == requestCode }.first() } typealias ActivityCallback = (activity: Activity) -> Unit diff --git a/ground/src/main/java/com/google/android/ground/system/GeocodingManager.kt b/ground/src/main/java/com/google/android/ground/system/GeocodingManager.kt index bcc06bf289..fba03be38a 100644 --- a/ground/src/main/java/com/google/android/ground/system/GeocodingManager.kt +++ b/ground/src/main/java/com/google/android/ground/system/GeocodingManager.kt @@ -111,7 +111,8 @@ constructor( * call on main thread. */ private fun fetchAddressesBlocking(coordinates: Coordinates): List
= - // TODO(#1762): Replace with non-blocking call with listener. + // TODO: Replace with non-blocking call with listener. + // Issue URL: https://github.com/google/ground-android/issues/1762 try { geocoder.getFromLocation(coordinates.lat, coordinates.lng, 5) ?: listOf() } catch (e: Exception) { diff --git a/ground/src/main/java/com/google/android/ground/system/LocationManager.kt b/ground/src/main/java/com/google/android/ground/system/LocationManager.kt index ab5d522901..cebf73900a 100644 --- a/ground/src/main/java/com/google/android/ground/system/LocationManager.kt +++ b/ground/src/main/java/com/google/android/ground/system/LocationManager.kt @@ -50,6 +50,7 @@ constructor( private val locationCallback = LocationSharedFlowCallback(_locationUpdates, externalScope) // TODO: Request updates on resume. + // Issue URL: https://github.com/google/ground-android/issues/2624 /** Immediately emits the last known location (if any) and then subscribes to location updates. */ suspend fun requestLocationUpdates() { locationClient.getLastLocation()?.let { _locationUpdates.emit(it) } @@ -57,5 +58,6 @@ constructor( } // TODO: Remove updates on pause. + // Issue URL: https://github.com/google/ground-android/issues/2624 suspend fun disableLocationUpdates() = locationClient.removeLocationUpdates(locationCallback) } diff --git a/ground/src/main/java/com/google/android/ground/system/auth/GoogleAuthenticationManager.kt b/ground/src/main/java/com/google/android/ground/system/auth/GoogleAuthenticationManager.kt index 8035bec4cb..651529d756 100644 --- a/ground/src/main/java/com/google/android/ground/system/auth/GoogleAuthenticationManager.kt +++ b/ground/src/main/java/com/google/android/ground/system/auth/GoogleAuthenticationManager.kt @@ -98,6 +98,7 @@ constructor( private fun getGoogleSignInClient(activity: Activity): GoogleSignInClient = // TODO: Use app context instead of activity? + // Issue URL: https://github.com/google/ground-android/issues/2912 GoogleSignIn.getClient(activity, googleSignInOptions) private fun onActivityResult(activityResult: ActivityResult) { diff --git a/ground/src/main/java/com/google/android/ground/ui/IconFactory.kt b/ground/src/main/java/com/google/android/ground/ui/IconFactory.kt index 6943d66aa1..2ecc9e750a 100644 --- a/ground/src/main/java/com/google/android/ground/ui/IconFactory.kt +++ b/ground/src/main/java/com/google/android/ground/ui/IconFactory.kt @@ -63,7 +63,6 @@ class IconFactory @Inject constructor(@ApplicationContext private val context: C /** Returns a [BitmapDescriptor] for representing an individual marker on the map. */ fun getMarkerIcon(color: Int, scale: Float): BitmapDescriptor { val bitmap = getMarkerBitmap(color, scale) - // TODO: Cache rendered bitmaps. return BitmapDescriptorFactory.fromBitmap(bitmap) } diff --git a/ground/src/main/java/com/google/android/ground/ui/common/BaseMapViewModel.kt b/ground/src/main/java/com/google/android/ground/ui/common/BaseMapViewModel.kt index b238edc1a7..eeee724f6a 100644 --- a/ground/src/main/java/com/google/android/ground/ui/common/BaseMapViewModel.kt +++ b/ground/src/main/java/com/google/android/ground/ui/common/BaseMapViewModel.kt @@ -89,7 +89,8 @@ constructor( } .stateIn(viewModelScope, SharingStarted.Lazily, R.color.md_theme_onSurfaceVariant) - // TODO(#1789): Consider adding another icon for representing "GPS disabled" state. + // TODO: Consider adding another icon for representing "GPS disabled" state. + // Issue URL: https://github.com/google/ground-android/issues/1789 val locationLockIcon = locationLock .map { lockState -> @@ -233,7 +234,8 @@ constructor( delay(3000) } - // TODO(#1889): Track the zoom level in a VM associated with the MapFragment and use here + // TODO: Track the zoom level in a VM associated with the MapFragment and use here + // Issue URL: https://github.com/google/ground-android/issues/1889 NewCameraPositionViaCoordinates(coordinates, shouldAnimate = true) } diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/AbstractTaskFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/AbstractTaskFragment.kt index 71312e8f79..5f54186364 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/AbstractTaskFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/AbstractTaskFragment.kt @@ -224,8 +224,9 @@ abstract class AbstractTaskFragment : AbstractFragmen horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth().padding(8.dp), ) { - // TODO(#2417): Previous button should always be positioned to the left of the screen. + // TODO: Previous button should always be positioned to the left of the screen. // Rest buttons should be aligned to the right side of the screen. + // Issue URL: https://github.com/google/ground-android/issues/2417 buttonDataList.sortedBy { it.index }.forEach { (_, button) -> button.CreateButton() } } } diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskViewModel.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskViewModel.kt index 4a27ca553a..4a31ab29ce 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskViewModel.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskViewModel.kt @@ -50,7 +50,6 @@ constructor( pinColor = job.getDefaultColor() // Drop a marker for current value - // TODO: The restored marker appears to be slightly shifted. Check for accuracy of lat/lng. (taskData as? DropPinTaskData)?.let { dropMarker(it.location) } } @@ -80,7 +79,6 @@ constructor( id = uuidGenerator.generateUuid(), type = FeatureType.USER_POINT.ordinal, geometry = point, - // TODO: Set correct pin color. style = Feature.Style(pinColor), clusterable = false, selected = true, diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt index 36b7e84dfa..bc838df97c 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt @@ -60,8 +60,8 @@ class DrawAreaTaskFragment @Inject constructor() : AbstractTaskFragment = MutableSharedFlow() val openDrawerRequestsFlow: SharedFlow = _openDrawerRequests.asSharedFlow() - // TODO(#1730): Allow tile source configuration from a non-survey accessible source. + // TODO: Allow tile source configuration from a non-survey accessible source. + // Issue URL: https://github.com/google/ground-android/issues/1730 val showOfflineAreaMenuItem: LiveData = MutableLiveData(true) init { @@ -92,6 +93,7 @@ internal constructor( } // TODO: Check whether the previous user id matches with current user or not. + // Issue URL: https://github.com/google/ground-android/issues/2903 return draft } diff --git a/ground/src/main/java/com/google/android/ground/ui/home/mapcontainer/HomeScreenMapContainerFragment.kt b/ground/src/main/java/com/google/android/ground/ui/home/mapcontainer/HomeScreenMapContainerFragment.kt index c9bbf82fdf..744dd2e14a 100644 --- a/ground/src/main/java/com/google/android/ground/ui/home/mapcontainer/HomeScreenMapContainerFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/home/mapcontainer/HomeScreenMapContainerFragment.kt @@ -153,7 +153,8 @@ class HomeScreenMapContainerFragment : AbstractMapContainerFragment() { ) { if (!canUserSubmitData) { // Skip data collection screen if the user can't submit any data - // TODO(#1667): Revisit UX for displaying view only mode + // TODO: Revisit UX for displaying view only mode + // Issue URL: https://github.com/google/ground-android/issues/1667 ephemeralPopups.ErrorPopup().show(getString(R.string.collect_data_viewer_error)) return } diff --git a/ground/src/main/java/com/google/android/ground/ui/home/mapcontainer/HomeScreenMapContainerViewModel.kt b/ground/src/main/java/com/google/android/ground/ui/home/mapcontainer/HomeScreenMapContainerViewModel.kt index 45b57dcde9..ea49421607 100644 --- a/ground/src/main/java/com/google/android/ground/ui/home/mapcontainer/HomeScreenMapContainerViewModel.kt +++ b/ground/src/main/java/com/google/android/ground/ui/home/mapcontainer/HomeScreenMapContainerViewModel.kt @@ -127,9 +127,6 @@ internal constructor( init { // THIS SHOULD NOT BE CALLED ON CONFIG CHANGE - // TODO: Clear location of interest markers when survey is deactivated. - // TODO: Since we depend on survey stream from repo anyway, this transformation can be moved - // into the repository. @OptIn(FlowPreview::class) mapLoiFeatures = diff --git a/ground/src/main/java/com/google/android/ground/ui/map/gms/GmsExt.kt b/ground/src/main/java/com/google/android/ground/ui/map/gms/GmsExt.kt index d125d84dc7..3fecdc8957 100644 --- a/ground/src/main/java/com/google/android/ground/ui/map/gms/GmsExt.kt +++ b/ground/src/main/java/com/google/android/ground/ui/map/gms/GmsExt.kt @@ -36,7 +36,8 @@ object GmsExt { fun Bounds.center(): Coordinates = toGoogleMapsObject().center.toModelObject() fun List.toBounds(): Bounds? { - // TODO(#1825): Don't use shell coordinates for polygon and multi-polygons. + // TODO: Don't use shell coordinates for polygon and multi-polygons. + // Issue URL: https://github.com/google/ground-android/issues/1825 val coordinates = this.flatMap { it.getShellCoordinates() } if (coordinates.isNotEmpty()) { val bounds = LatLngBounds.builder() diff --git a/ground/src/main/java/com/google/android/ground/ui/map/gms/GoogleMapsFragment.kt b/ground/src/main/java/com/google/android/ground/ui/map/gms/GoogleMapsFragment.kt index 0668fa622c..4a5122f97b 100644 --- a/ground/src/main/java/com/google/android/ground/ui/map/gms/GoogleMapsFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/map/gms/GoogleMapsFragment.kt @@ -108,6 +108,7 @@ class GoogleMapsFragment : SupportMapFragment(), MapFragment { private fun onApplyWindowInsets(view: View, insets: WindowInsetsCompat): WindowInsetsCompat { // TODO: Move extra padding to dimens.xml. + // Issue URL: https://github.com/google/ground-android/issues/2913 // HACK: Fix padding when keyboard is shown; we limit the padding here to prevent the // watermark from flying up too high due to the combination of translateY and big inset // size due to keyboard. @@ -279,7 +280,8 @@ class GoogleMapsFragment : SupportMapFragment(), MapFragment { } private fun addRemoteMogTileOverlay(url: String) { - // TODO(#1730): Make sub-paths configurable and stop hardcoding here. + // TODO: Make sub-paths configurable and stop hardcoding here. + // Issue URL: https://github.com/google/ground-android/issues/1730 val mogCollection = MogCollection(Config.getMogSources(url)) addTileOverlay(MogTileProvider(mogCollection, remoteStorageManager)) } diff --git a/ground/src/main/java/com/google/android/ground/ui/map/gms/features/PointRenderer.kt b/ground/src/main/java/com/google/android/ground/ui/map/gms/features/PointRenderer.kt index 77e844a57a..0cb02d86c1 100644 --- a/ground/src/main/java/com/google/android/ground/ui/map/gms/features/PointRenderer.kt +++ b/ground/src/main/java/com/google/android/ground/ui/map/gms/features/PointRenderer.kt @@ -61,10 +61,12 @@ constructor(resources: Resources, private val markerIconFactory: IconFactory) : } private fun getMarkerIcon(style: Feature.Style, selected: Boolean): BitmapDescriptor { - // TODO(#2167): Allow icon to be updated so we can update scale based on zoom level. + // TODO: Allow icon to be updated so we can update scale based on zoom level. + // Issue URL: https://github.com/google/ground-android/issues/2167 var scale = defaultMarkerScale if (selected) { - // TODO(#2168): Improve selected marker styling. + // TODO: Improve selected marker styling. + // Issue URL: https://github.com/google/ground-android/issues/2168 scale *= selectedMarkerScaleFactor } return markerIconFactory.getMarkerIcon(style.color, scale) diff --git a/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogClient.kt b/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogClient.kt index 7835a53e73..616c91bce3 100644 --- a/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogClient.kt +++ b/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogClient.kt @@ -93,7 +93,8 @@ class MogClient(val collection: MogCollection, val remoteStorageManager: RemoteS */ @OptIn(ExperimentalCoroutinesApi::class) fun getTiles(requests: List): Flow = flow { - // TODO(#1704): Use thread pool to request multiple ranges in parallel. + // TODO: Use thread pool to request multiple ranges in parallel. + // Issue URL: https://github.com/google/ground-android/issues/1704 val results = mutableListOf>>() withContext(Dispatchers.IO.limitedParallelism(200)) { for (request in requests) { @@ -178,6 +179,7 @@ class MogClient(val collection: MogCollection, val remoteStorageManager: RemoteS mogBounds: TileCoordinates, ): Deferred = runBlocking { // TODO: Exceptions get propagated as cancellation of the coroutine. Handle them! + // Issue URL: https://github.com/google/ground-android/issues/2903 async { path.toUrl()?.readMetadata(mogBounds) }.also { cache.put(path, it) } } diff --git a/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogImageMetadata.kt b/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogImageMetadata.kt index e7e042b8fe..ce347b6001 100644 --- a/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogImageMetadata.kt +++ b/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogImageMetadata.kt @@ -32,6 +32,7 @@ data class MogImageMetadata( private val tileCountY = imageLength / tileLength // TODO: Verify X and Y scales are the same. + // Issue URL: https://github.com/google/ground-android/issues/2915 val zoom = originTile.zoom fun hasTile(x: Int, y: Int) = @@ -81,6 +82,7 @@ data class MogImageMetadata( tiffTagToValue[TiffTag.TileWidth] as Int, tiffTagToValue[TiffTag.TileLength] as Int, // TODO: Refactor casts into typed accessors. + // Issue URL: https://github.com/google/ground-android/issues/2915 tiffTagToValue[TiffTag.TileOffsets] as List, tiffTagToValue[TiffTag.TileByteCounts] as List, tiffTagToValue[TiffTag.ImageWidth] as Int, diff --git a/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogMetadataReader.kt b/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogMetadataReader.kt index ea0bfcf412..726792cf4d 100644 --- a/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogMetadataReader.kt +++ b/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogMetadataReader.kt @@ -25,17 +25,20 @@ import java.util.* private const val NULL_CHAR = 0.toChar() -// TODO(#1596): Add unit tests. +// TODO: Add unit tests. +// Issue URL: https://github.com/google/ground-android/issues/1596 /** Instances of this class are not thread-safe. */ class MogMetadataReader(private val seekable: SeekableInputStream) { private lateinit var dataInput: DataInput // TODO: Refactor Map into its own class. + // Issue URL: https://github.com/google/ground-android/issues/2915 fun readImageFileDirectories(): List> { val byteOrderCode = readByteOrderString() dataInput = createDataInput(byteOrderCode) // TODO: Add support for BigTIFF. + // Issue URL: https://github.com/google/ground-android/issues/2914 val fileIdentifier = dataInput.readUnsignedShort() validateFileIdentifier(fileIdentifier) diff --git a/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogTileDownloader.kt b/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogTileDownloader.kt index a5b66b0eea..edc9d95438 100644 --- a/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogTileDownloader.kt +++ b/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogTileDownloader.kt @@ -27,7 +27,8 @@ import timber.log.Timber * @param outputBasePath the base path on the local file system where tiles should be written. */ class MogTileDownloader(private val client: MogClient, private val outputBasePath: String) { - // TODO(#1755): Add test coverage to this class and entire package. + // TODO: Add test coverage to this class and entire package. + // Issue URL: https://github.com/google/ground-android/issues/1755 /** * Executes the provided [requests], writing resulting tiles to [outputBasePath] in sub-paths of * the form `{z}/{x}/{y}.jpg`. diff --git a/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogTileProvider.kt b/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogTileProvider.kt index 2dc98ebd69..ff5c21282b 100644 --- a/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogTileProvider.kt +++ b/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogTileProvider.kt @@ -22,7 +22,8 @@ import com.google.android.ground.persistence.remote.RemoteStorageManager import kotlinx.coroutines.runBlocking import timber.log.Timber -// TODO(#1596): Add unit tests. +// TODO: Add unit tests. +// Issue URL: https://github.com/google/ground-android/issues/1596 /** Fetches and returns MOG tiles to Maps SDK for display as a tile overlay. */ class MogTileProvider(collection: MogCollection, remoteStorageManager: RemoteStorageManager) : TileProvider { diff --git a/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogTileReader.kt b/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogTileReader.kt index 589681ac98..81cd3e6f8b 100644 --- a/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogTileReader.kt +++ b/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogTileReader.kt @@ -21,7 +21,8 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import timber.log.Timber -// TODO(#1596): Add unit tests. +// TODO: Add unit tests. +// Issue URL: https://github.com/google/ground-android/issues/1596 /** Reads tiles from an [InputStream]. */ class MogTileReader(private val inputStream: InputStream, initialOffset: Long) { private var offset: Long = initialOffset diff --git a/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogTilesRequest.kt b/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogTilesRequest.kt index 1f65b42cee..e11bd8f1c8 100644 --- a/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogTilesRequest.kt +++ b/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/MogTilesRequest.kt @@ -16,7 +16,8 @@ package com.google.android.ground.ui.map.gms.mog -// TODO(#1596): Add unit tests. +// TODO: Add unit tests. +// Issue URL: https://github.com/google/ground-android/issues/1596 /** A set of [tiles] to be fetched from [sourceUrl] in a single request. */ open class MogTilesRequest(val sourceUrl: String, val tiles: List) { val totalBytes: Int diff --git a/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/README.md b/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/README.md index ff5a6fe0da..dcab5c1cdf 100644 --- a/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/README.md +++ b/ground/src/main/java/com/google/android/ground/ui/map/gms/mog/README.md @@ -36,5 +36,3 @@ To simplify discovery and retrieval, MOGs are organized in collections structure See [Map and Tile Coordinates](https://developers.google.com/maps/documentation/android-sdk/coordinates) in the Google Maps Platform docs for info. - - diff --git a/ground/src/main/java/com/google/android/ground/ui/offlineareas/selector/OfflineAreaSelectorFragment.kt b/ground/src/main/java/com/google/android/ground/ui/offlineareas/selector/OfflineAreaSelectorFragment.kt index bbea178bb4..5d04d18dea 100644 --- a/ground/src/main/java/com/google/android/ground/ui/offlineareas/selector/OfflineAreaSelectorFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/offlineareas/selector/OfflineAreaSelectorFragment.kt @@ -102,8 +102,8 @@ class OfflineAreaSelectorFragment : AbstractMapContainerFragment() { AppTheme { DownloadProgressDialog( progress = progress.value, - // TODO - Add Download Cancel Feature - // https://github.com/google/ground-android/issues/2884 + // TODO: - Add Download Cancel Feature + // Issue URL: https://github.com/google/ground-android/issues/1596 onDismiss = { openAlertDialog.value = false }, ) } diff --git a/ground/src/main/java/com/google/android/ground/ui/offlineareas/viewer/OfflineAreaViewerFragment.kt b/ground/src/main/java/com/google/android/ground/ui/offlineareas/viewer/OfflineAreaViewerFragment.kt index f4e8aa0f62..6c1103db8e 100644 --- a/ground/src/main/java/com/google/android/ground/ui/offlineareas/viewer/OfflineAreaViewerFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/offlineareas/viewer/OfflineAreaViewerFragment.kt @@ -40,7 +40,8 @@ class OfflineAreaViewerFragment @Inject constructor() : AbstractMapContainerFrag override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - // TODO(#2649) requireNotNull will throw error, it should be handle smoothly + // TODO: requireNotNull will throw error, it should be handle smoothly + // Issue URL: https://github.com/google/ground-android/issues/2649 val args = OfflineAreaViewerFragmentArgs.fromBundle(requireNotNull(arguments)) viewModel = getViewModel(OfflineAreaViewerViewModel::class.java) viewModel.initialize(args.offlineAreaId) diff --git a/ground/src/main/java/com/google/android/ground/ui/settings/SettingsFragment.kt b/ground/src/main/java/com/google/android/ground/ui/settings/SettingsFragment.kt index 33afa31dda..da3eb0e789 100644 --- a/ground/src/main/java/com/google/android/ground/ui/settings/SettingsFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/settings/SettingsFragment.kt @@ -30,8 +30,6 @@ import com.google.android.ground.R * * NOTE: It uses [PreferenceFragmentCompat] instead of [ ], so dagger can't inject into it like it * does in other fragments. - * - * TODO: Create dagger module and support injection into this fragment. */ class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceClickListener { diff --git a/ground/src/main/java/com/google/android/ground/ui/surveyselector/SurveySelectorFragment.kt b/ground/src/main/java/com/google/android/ground/ui/surveyselector/SurveySelectorFragment.kt index 8e0ea89b66..d2be09248e 100644 --- a/ground/src/main/java/com/google/android/ground/ui/surveyselector/SurveySelectorFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/surveyselector/SurveySelectorFragment.kt @@ -101,7 +101,6 @@ class SurveySelectorFragment : AbstractFragment(), BackPressListener { binding.recyclerView.adapter = adapter getAbstractActivity().setSupportActionBar(binding.toolbar) - // TODO - https://github.com/google/ground-android/issues/2692#issuecomment-2430978043 if (parentFragmentManager.backStackEntryCount > 0) { getAbstractActivity().supportActionBar?.setDisplayHomeAsUpEnabled(true) } else { diff --git a/ground/src/main/res/layout/main_act.xml b/ground/src/main/res/layout/main_act.xml index cf16e9bd73..57d63acd00 100644 --- a/ground/src/main/res/layout/main_act.xml +++ b/ground/src/main/res/layout/main_act.xml @@ -33,7 +33,6 @@ Translucent scrim to make status bar legible when shown overlaid on map or toolbar. Workaround for possible bug in Navigation Architecture Components where translucent system bars get replaced with solid white background in fragment after navigation. - TODO: Is this a bug? If so, what's the bug ID? Has it been fixed? --> - + + - - + + 48dp - 4dp diff --git a/ground/src/main/res/xml/preferences.xml b/ground/src/main/res/xml/preferences.xml index e485bb328f..c5649e8f48 100644 --- a/ground/src/main/res/xml/preferences.xml +++ b/ground/src/main/res/xml/preferences.xml @@ -41,7 +41,8 @@ app:summary="@string/ground_website" app:title="@string/visit_website_title" /> - + + , VM : AbstractT /** Asserts that the task fragment has the given list of buttons in the exact same order. */ protected fun assertFragmentHasButtons(vararg buttonActions: ButtonAction) { // TODO: Also verify the visibility/state of the button + // Issue URL: https://github.com/google/ground-android/issues/2134 assertThat(fragment.buttonDataList.map { it.button.getAction() }) .containsExactlyElementsIn(buttonActions) buttonActions.withIndex().forEach { (index, expected) -> diff --git a/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/date/DateTaskFragmentTest.kt b/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/date/DateTaskFragmentTest.kt index c1b9644c85..b9c56b4f40 100644 --- a/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/date/DateTaskFragmentTest.kt +++ b/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/date/DateTaskFragmentTest.kt @@ -42,6 +42,7 @@ import org.mockito.Mock import org.robolectric.RobolectricTestRunner // TODO: Add a test for selecting a date and verifying response. +// Issue URL: https://github.com/google/ground-android/issues/2134 @HiltAndroidTest @RunWith(RobolectricTestRunner::class) diff --git a/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragmentTest.kt b/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragmentTest.kt index f1bbde6acb..f9c3ad3b19 100644 --- a/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragmentTest.kt +++ b/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragmentTest.kt @@ -197,7 +197,6 @@ class DrawAreaTaskFragmentTest : private fun updateLastVertexAndAddPoint(coordinate: Coordinates) { updateLastVertex(coordinate, false) - // TODO: Refactor and move one level up with the rest of the runner logic. runner().clickButton("Add point") } diff --git a/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskViewModelTest.kt b/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskViewModelTest.kt index b9f81326fe..aa78d8560e 100644 --- a/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskViewModelTest.kt +++ b/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskViewModelTest.kt @@ -41,8 +41,6 @@ import org.mockito.Mockito.doNothing import org.mockito.Mockito.mock import org.robolectric.RobolectricTestRunner -// TODO: Convert to fragment test for better coverage - @HiltAndroidTest @RunWith(RobolectricTestRunner::class) class DrawAreaTaskViewModelTest : BaseHiltTest() { diff --git a/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/time/TimeTaskFragmentTest.kt b/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/time/TimeTaskFragmentTest.kt index 8a31b838d3..ed1ac18106 100644 --- a/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/time/TimeTaskFragmentTest.kt +++ b/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/time/TimeTaskFragmentTest.kt @@ -41,6 +41,7 @@ import org.mockito.Mock import org.robolectric.RobolectricTestRunner // TODO: Add a test for selecting a time and verifying response. +// Issue URL: https://github.com/google/ground-android/issues/2134 @HiltAndroidTest @RunWith(RobolectricTestRunner::class) diff --git a/ground/src/test/java/com/google/android/ground/ui/home/HomeScreenFragmentTest.kt b/ground/src/test/java/com/google/android/ground/ui/home/HomeScreenFragmentTest.kt index a04c5d76f6..88b5fcbf8c 100644 --- a/ground/src/test/java/com/google/android/ground/ui/home/HomeScreenFragmentTest.kt +++ b/ground/src/test/java/com/google/android/ground/ui/home/HomeScreenFragmentTest.kt @@ -279,7 +279,8 @@ class NavigationDrawerItemClickTest( @ParameterizedRobolectricTestRunner.Parameters(name = "{3}") fun data() = listOf( - // TODO(#2385): Restore tests deleted in #2382. + // TODO: Restore tests deleted in #2382. + // Issue URL: https://github.com/google/ground-android/issues/2385 arrayOf("Data sync status", R.id.sync_status_fragment, TEST_SURVEY, true), arrayOf("Terms of service", R.id.terms_of_service_fragment, TEST_SURVEY, true), arrayOf("About", R.id.aboutFragment, TEST_SURVEY, true), diff --git a/ground/src/test/resources/robolectric.properties b/ground/src/test/resources/robolectric.properties index afdfbc71fb..8ab6b9e2ec 100644 --- a/ground/src/test/resources/robolectric.properties +++ b/ground/src/test/resources/robolectric.properties @@ -1,3 +1,4 @@ # src/test/resources/robolectric.properties -# TODO(#2246): Remove the need for this file after upgrading Robolectric tests to API 33 +# TODO: Remove the need for this file after upgrading Robolectric tests to API 33 +# Issue URL: https://github.com/google/ground-android/issues/2246 sdk=30 \ No newline at end of file diff --git a/sharedTest/src/main/kotlin/com/sharedtest/FakeData.kt b/sharedTest/src/main/kotlin/com/sharedtest/FakeData.kt index f21b1b8582..aa20cbca97 100644 --- a/sharedTest/src/main/kotlin/com/sharedtest/FakeData.kt +++ b/sharedTest/src/main/kotlin/com/sharedtest/FakeData.kt @@ -48,6 +48,7 @@ import java.util.Date */ object FakeData { // TODO: Replace constants with calls to newFoo() methods. + // Issue URL: https://github.com/google/ground-android/issues/2917 val TERMS_OF_SERVICE: TermsOfService = TermsOfService("TERMS_OF_SERVICE", "Fake Terms of Service text") const val JOB_ID = "job id" diff --git a/sharedTest/src/main/kotlin/com/sharedtest/system/auth/FakeAuthenticationManager.kt b/sharedTest/src/main/kotlin/com/sharedtest/system/auth/FakeAuthenticationManager.kt index 1e48dc018a..06393f2214 100644 --- a/sharedTest/src/main/kotlin/com/sharedtest/system/auth/FakeAuthenticationManager.kt +++ b/sharedTest/src/main/kotlin/com/sharedtest/system/auth/FakeAuthenticationManager.kt @@ -38,8 +38,6 @@ constructor(@ApplicationScope private val externalScope: CoroutineScope) : private val _signInStateFlow = MutableStateFlow(null) override val signInState: Flow = _signInStateFlow.asStateFlow().filterNotNull() - // TODO: Remove default user once instrumentation tests can set it during the test. Currently, the - // activity gets launched before the user can be set in setUp() private var currentUser: User = FakeData.USER fun setUser(user: User) {