Skip to content

Commit

Permalink
Merge branch 'master' into sufy/2115/offline-imagery
Browse files Browse the repository at this point in the history
  • Loading branch information
sufyanAbbasi committed Feb 15, 2024
2 parents 0a13b9b + 8e23ba1 commit 783b045
Show file tree
Hide file tree
Showing 32 changed files with 505 additions and 234 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,11 @@ class GroundApplication : MultiDexApplication(), Configuration.Provider {
@Inject lateinit var crashReportingTree: CrashReportingTree
@Inject lateinit var workerFactory: HiltWorkerFactory

init {
Timber.plant(if (isReleaseBuild()) crashReportingTree else Timber.DebugTree())
}

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

override fun onCreate() {
super.onCreate()
Timber.plant(if (isReleaseBuild()) crashReportingTree else Timber.DebugTree())
if (!isReleaseBuild()) {
Timber.d("DEBUG build config active; enabling debug tooling")

Expand Down
12 changes: 6 additions & 6 deletions ground/src/main/java/com/google/android/ground/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/
package com.google.android.ground

import android.app.ProgressDialog
import android.app.AlertDialog
import android.content.Intent
import android.os.Bundle
import androidx.core.view.WindowInsetsCompat
Expand All @@ -33,7 +33,7 @@ import com.google.android.ground.ui.common.NavigateTo
import com.google.android.ground.ui.common.NavigateUp
import com.google.android.ground.ui.common.NavigationRequest
import com.google.android.ground.ui.common.Navigator
import com.google.android.ground.ui.common.ProgressDialogs
import com.google.android.ground.ui.common.ProgressDialogs.modalSpinner
import com.google.android.ground.ui.common.ViewModelFactory
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
Expand All @@ -55,7 +55,7 @@ class MainActivity : AbstractActivity() {
private lateinit var viewModel: MainViewModel
private lateinit var navHostFragment: NavHostFragment

private var signInProgressDialog: ProgressDialog? = null
private var signInProgressDialog: AlertDialog? = null

override fun onCreate(savedInstanceState: Bundle?) {
// Make sure this is before calling super.onCreate()
Expand Down Expand Up @@ -146,14 +146,14 @@ class MainActivity : AbstractActivity() {

private fun showSignInDialog() {
if (signInProgressDialog == null) {
signInProgressDialog = ProgressDialogs.modalSpinner(this, R.string.signing_in)
signInProgressDialog = modalSpinner(this, layoutInflater, R.string.signing_in)
}
signInProgressDialog!!.show()
signInProgressDialog?.show()
}

private fun dismissSignInDialog() {
if (signInProgressDialog != null) {
signInProgressDialog!!.dismiss()
signInProgressDialog?.dismiss()
signInProgressDialog = null
}
}
Expand Down
13 changes: 11 additions & 2 deletions ground/src/main/java/com/google/android/ground/model/job/Job.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,24 @@ data class Job(
UNKNOWN
}

class TaskNotFoundException(taskId: String) : Throwable(message = "unknown task $taskId")

val canDataCollectorsAddLois: Boolean
get() = strategy != DataCollectionStrategy.PREDEFINED

val tasksSorted: List<Task>
get() = tasks.values.sortedBy { it.index }

fun getTask(id: String): Task = tasks[id] ?: error("Unknown task id $id")
// TODO(#2216): Consider using nulls to indicate absence of value here instead of throwing
// an exception.
fun getTask(id: String): Task = tasks[id] ?: throw TaskNotFoundException(id)

fun getAddLoiTask(): Task? = tasks.values.firstOrNull { it.isAddLoiTask }
/** Job must contain at-most 1 `AddLoiTask`. */
fun getAddLoiTask(): Task? =
tasks.values
.filter { it.isAddLoiTask }
.apply { check(size <= 1) { "Expected 0 or 1, found $size AddLoiTasks" } }
.firstOrNull()

/** Returns true if the job has one or more tasks. */
fun hasTasks() = tasks.values.isNotEmpty()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ object SubmissionDataConverter {
ValueJsonConverter.toResponse(task, jsonObject[taskId])?.let { map[taskId] = it }
} catch (e: LocalDataConsistencyException) {
Timber.d("Bad submission data in local db: ${e.message}")
} catch (e: Job.TaskNotFoundException) {
Timber.d(e, "Ignoring data for unknown task")
}
}
} catch (e: JSONException) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ object SubmissionDeltasConverter {
Timber.d("Bad submission value in local db: " + e.message)
} catch (e: DataStoreException) {
Timber.d("Bad submission value in local db: " + e.message)
} catch (e: Job.TaskNotFoundException) {
Timber.d(e, "Ignoring delta for unknown task")
}
}
} catch (e: JSONException) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,18 +85,23 @@ internal object SubmissionConverter {
}

private fun putValue(taskId: String, job: Job, obj: Any, data: MutableMap<String, Value>) {
val task = job.getTask(taskId)
when (task.type) {
Task.Type.PHOTO,
Task.Type.TEXT -> putTextResponse(taskId, obj, data)
Task.Type.MULTIPLE_CHOICE -> putMultipleChoiceResponse(taskId, task.multipleChoice, obj, data)
Task.Type.NUMBER -> putNumberResponse(taskId, obj, data)
Task.Type.DATE -> putDateResponse(taskId, obj, data)
Task.Type.TIME -> putTimeResponse(taskId, obj, data)
Task.Type.DROP_PIN -> putDropPinTaskResult(taskId, obj, data)
Task.Type.DRAW_AREA -> putDrawAreaTaskResult(taskId, obj, data)
Task.Type.CAPTURE_LOCATION -> putCaptureLocationResult(taskId, obj, data)
else -> throw DataStoreException("Unknown type " + task.type)
try {
val task = job.getTask(taskId)
when (task.type) {
Task.Type.PHOTO,
Task.Type.TEXT -> putTextResponse(taskId, obj, data)
Task.Type.MULTIPLE_CHOICE ->
putMultipleChoiceResponse(taskId, task.multipleChoice, obj, data)
Task.Type.NUMBER -> putNumberResponse(taskId, obj, data)
Task.Type.DATE -> putDateResponse(taskId, obj, data)
Task.Type.TIME -> putTimeResponse(taskId, obj, data)
Task.Type.DROP_PIN -> putDropPinTaskResult(taskId, obj, data)
Task.Type.DRAW_AREA -> putDrawAreaTaskResult(taskId, obj, data)
Task.Type.CAPTURE_LOCATION -> putCaptureLocationResult(taskId, obj, data)
else -> throw DataStoreException("Unknown type " + task.type)
}
} catch (e: Job.TaskNotFoundException) {
Timber.d(e, "cannot put value for unknown task")
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,21 +67,21 @@ constructor(

/**
* Returns all LOI and submission mutations in the local mutation queue relating to LOI with the
* specified id.
* specified id, sorted by creation timestamp (oldest first).
*/
suspend fun getMutations(
loidId: String,
loiId: String,
vararg entitySyncStatus: MutationEntitySyncStatus
): List<Mutation> {
val loiMutations =
localLocationOfInterestStore
.findByLocationOfInterestId(loidId, *entitySyncStatus)
.findByLocationOfInterestId(loiId, *entitySyncStatus)
.map(LocationOfInterestMutationEntity::toModelObject)
val submissionMutations =
localSubmissionStore.findByLocationOfInterestId(loidId, *entitySyncStatus).map {
localSubmissionStore.findByLocationOfInterestId(loiId, *entitySyncStatus).map {
it.toSubmissionMutation()
}
return loiMutations + submissionMutations
return (loiMutations + submissionMutations).sortedBy { it.clientTimestamp }
}

private suspend fun SubmissionMutationEntity.toSubmissionMutation(): SubmissionMutation =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,19 @@
*/
package com.google.android.ground.ui.common

import android.app.AlertDialog
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.IdRes
import androidx.annotation.StringRes
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel
import com.google.android.ground.AbstractActivity
import com.google.android.ground.R
import com.google.android.ground.ui.common.ProgressDialogs.modalSpinner
import com.google.android.ground.ui.util.ViewUtil
import com.google.android.ground.util.Debug
import javax.inject.Inject
Expand All @@ -32,6 +36,8 @@ abstract class AbstractFragment : Fragment() {

@Inject lateinit var viewModelFactory: ViewModelFactory

private var progressDialog: AlertDialog? = null

protected fun <T : ViewModel> getViewModel(modelClass: Class<T>): T =
viewModelFactory.get(this, modelClass)

Expand All @@ -48,7 +54,7 @@ abstract class AbstractFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
savedInstanceState: Bundle?,
): View? {
Debug.logLifecycleEvent(this)
return super.onCreateView(inflater, container, savedInstanceState)
Expand Down Expand Up @@ -110,4 +116,18 @@ abstract class AbstractFragment : Fragment() {
}

protected fun getAbstractActivity(): AbstractActivity = requireActivity() as AbstractActivity

protected fun showProgressDialog(@StringRes messageId: Int = R.string.loading) {
if (progressDialog == null) {
progressDialog = modalSpinner(messageId)
}
progressDialog?.show()
}

protected fun dismissProgressDialog() {
if (progressDialog != null) {
progressDialog?.dismiss()
progressDialog = null
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.StringRes
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
Expand All @@ -42,7 +43,7 @@ abstract class AbstractMapFragmentWithControls : AbstractMapContainerFragment()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
savedInstanceState: Bundle?,
): View {
binding = MapTaskFragBinding.inflate(inflater, container, false)
binding.fragment = this
Expand All @@ -53,7 +54,7 @@ abstract class AbstractMapFragmentWithControls : AbstractMapContainerFragment()
repeatOnLifecycle(Lifecycle.State.STARTED) {
getMapViewModel().location.collect {
val locationText = it?.toCaptureLocationResult()?.getDetailsText()
setCurrentLocationAsInfoCard(locationText)
updateLocationInfoCard(R.string.current_location, locationText)
}
}
}
Expand All @@ -67,11 +68,11 @@ abstract class AbstractMapFragmentWithControls : AbstractMapContainerFragment()
return binding.root
}

private fun setCurrentLocationAsInfoCard(locationText: String?) {
private fun updateLocationInfoCard(@StringRes title: Int, locationText: String?) {
if (locationText.isNullOrEmpty()) {
binding.infoCard.visibility = View.GONE
} else {
binding.cardTitle.setText(R.string.current_location)
binding.cardTitle.setText(title)
binding.cardValue.text = locationText
binding.infoCard.visibility = View.VISIBLE
}
Expand All @@ -85,6 +86,6 @@ abstract class AbstractMapFragmentWithControls : AbstractMapContainerFragment()
}
val target = position.target
val processedCoordinates = LatLngConverter.formatCoordinates(target)
setCurrentLocationAsInfoCard(processedCoordinates)
updateLocationInfoCard(R.string.map_location, processedCoordinates)
}
}

This file was deleted.

Loading

0 comments on commit 783b045

Please sign in to comment.