Skip to content

Commit

Permalink
Added partial load support for all data types except Draw (#2720)
Browse files Browse the repository at this point in the history
* added partial load support

* nit fix

* test fix

* fix onPause condition

* test fix

* frmt fix

* date and time fix

* nit fix

* clearing draft when empty

* on back fix

* suggested fix

* nit fixes

* suggested fix

* time fix

* fixed

* removeing test file

---------

Co-authored-by: Gino Miceli <228050+gino-m@users.noreply.github.com>
  • Loading branch information
anandwana001 and gino-m authored Sep 29, 2024
1 parent bb52291 commit 3b2fab4
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 142 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class DataCollectionFragment : AbstractFragment(), BackPressListener {
private lateinit var progressBar: ProgressBar
private lateinit var guideline: Guideline
private lateinit var viewPager: ViewPager2
private var isNavigatingUp = false

override fun onCreateView(
inflater: LayoutInflater,
Expand All @@ -71,6 +72,7 @@ class DataCollectionFragment : AbstractFragment(), BackPressListener {
getAbstractActivity().setSupportActionBar(binding.dataCollectionToolbar)

binding.dataCollectionToolbar.setNavigationOnClickListener {
isNavigatingUp = true
viewModel.clearDraft()
navigator.navigateUp()
}
Expand Down Expand Up @@ -108,6 +110,18 @@ class DataCollectionFragment : AbstractFragment(), BackPressListener {
lifecycleScope.launch { viewModel.uiState.filterNotNull().collect { updateUI(it) } }
}

override fun onResume() {
super.onResume()
isNavigatingUp = false
}

override fun onPause() {
super.onPause()
if (!isNavigatingUp) {
viewModel.saveCurrentState()
}
}

private fun updateUI(uiState: UiState) {
when (uiState) {
is UiState.TaskListAvailable -> loadTasks(uiState.tasks, uiState.taskPosition)
Expand Down Expand Up @@ -179,6 +193,7 @@ class DataCollectionFragment : AbstractFragment(), BackPressListener {

override fun onBack(): Boolean =
if (viewPager.currentItem == 0) {
isNavigatingUp = true
// If the user is currently looking at the first step, allow the system to handle the
// Back button. This calls finish() on this activity and pops the back stack.
viewModel.clearDraft()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,21 @@ internal constructor(
}
}

fun saveCurrentState() {
getTaskViewModel(currentTaskId.value)?.let {
if (!data.containsKey(it.task)) {
val validationError = it.validate()
if (validationError != null) {
return
}

data[it.task] = it.taskTaskData.value
savedStateHandle[TASK_POSITION_ID] = it.task.id
saveDraft()
}
}
}

private fun getDeltas(): List<ValueDelta> =
// Filter deltas to valid tasks.
data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,50 @@ import android.app.DatePickerDialog
import android.text.format.DateFormat
import android.view.LayoutInflater
import android.view.View
import androidx.lifecycle.LiveData
import androidx.lifecycle.asLiveData
import com.google.android.ground.databinding.DateTaskFragBinding
import com.google.android.ground.model.submission.DateTimeTaskData
import com.google.android.ground.ui.datacollection.components.TaskView
import com.google.android.ground.ui.datacollection.components.TaskViewFactory
import com.google.android.ground.ui.datacollection.tasks.AbstractTaskFragment
import dagger.hilt.android.AndroidEntryPoint
import java.util.*
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.map
import org.jetbrains.annotations.TestOnly

@AndroidEntryPoint
class DateTaskFragment : AbstractTaskFragment<DateTaskViewModel>() {

private var datePickerDialog: DatePickerDialog? = null

lateinit var dateText: LiveData<String>

override fun onTaskViewAttached() {
super.onTaskViewAttached()
dateText =
viewModel.taskTaskData
.filterIsInstance<DateTimeTaskData?>()
.map { taskData ->
if (taskData != null) {
val calendar = Calendar.getInstance()
calendar.timeInMillis = taskData.timeInMillis
getDateFormatter()?.format(calendar.time) ?: ""
} else {
""
}
}
.asLiveData()
}

override fun onCreateTaskView(inflater: LayoutInflater): TaskView =
TaskViewFactory.createWithHeader(inflater)

override fun onCreateTaskBody(inflater: LayoutInflater): View {
val taskBinding = DateTaskFragBinding.inflate(inflater)
taskBinding.lifecycleOwner = this
taskBinding.fragment = this
taskBinding.viewModel = viewModel
return taskBinding.root
}

Expand Down Expand Up @@ -67,7 +90,7 @@ class DateTaskFragment : AbstractTaskFragment<DateTaskViewModel>() {
}
}

fun getDateFormatter(): java.text.DateFormat? = DateFormat.getDateFormat(requireContext())
private fun getDateFormatter(): java.text.DateFormat? = DateFormat.getDateFormat(requireContext())

@TestOnly fun getDatePickerDialog(): DatePickerDialog? = datePickerDialog
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,10 @@ import com.google.android.ground.ui.datacollection.tasks.AbstractTaskViewModel
import java.text.DateFormat
import java.util.Date
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow

class DateTaskViewModel @Inject constructor() : AbstractTaskViewModel() {

private var _dateText: MutableStateFlow<String> = MutableStateFlow("")
val dateText = _dateText.asStateFlow()

fun updateResponse(dateFormat: DateFormat?, date: Date) {
dateFormat?.let {
_dateText.value = it.format(date)
setValue(fromMillis(date.time))
}
dateFormat?.let { setValue(fromMillis(date.time)) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,50 @@ import android.app.TimePickerDialog
import android.text.format.DateFormat
import android.view.LayoutInflater
import android.view.View
import androidx.lifecycle.LiveData
import androidx.lifecycle.asLiveData
import com.google.android.ground.databinding.TimeTaskFragBinding
import com.google.android.ground.model.submission.DateTimeTaskData
import com.google.android.ground.ui.datacollection.components.TaskView
import com.google.android.ground.ui.datacollection.components.TaskViewFactory
import com.google.android.ground.ui.datacollection.tasks.AbstractTaskFragment
import dagger.hilt.android.AndroidEntryPoint
import java.util.*
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.map
import org.jetbrains.annotations.TestOnly

@AndroidEntryPoint
class TimeTaskFragment : AbstractTaskFragment<TimeTaskViewModel>() {

private var timePickerDialog: TimePickerDialog? = null

lateinit var timeText: LiveData<String>

override fun onTaskViewAttached() {
super.onTaskViewAttached()
timeText =
viewModel.taskTaskData
.filterIsInstance<DateTimeTaskData?>()
.map { taskData ->
if (taskData != null) {
val calendar = Calendar.getInstance()
calendar.timeInMillis = taskData.timeInMillis
getTimeFormatter()?.format(calendar.time) ?: ""
} else {
""
}
}
.asLiveData()
}

override fun onCreateTaskView(inflater: LayoutInflater): TaskView =
TaskViewFactory.createWithHeader(inflater)

override fun onCreateTaskBody(inflater: LayoutInflater): View {
val taskBinding = TimeTaskFragBinding.inflate(inflater)
taskBinding.lifecycleOwner = this
taskBinding.fragment = this
taskBinding.viewModel = viewModel
return taskBinding.root
}

Expand All @@ -65,7 +88,7 @@ class TimeTaskFragment : AbstractTaskFragment<TimeTaskViewModel>() {
}
}

fun getTimeFormatter(): java.text.DateFormat? = DateFormat.getTimeFormat(requireContext())
private fun getTimeFormatter(): java.text.DateFormat? = DateFormat.getTimeFormat(requireContext())

@TestOnly fun getTimePickerDialog(): TimePickerDialog? = timePickerDialog
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,10 @@ import com.google.android.ground.ui.datacollection.tasks.AbstractTaskViewModel
import java.text.DateFormat
import java.util.Date
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow

class TimeTaskViewModel @Inject constructor() : AbstractTaskViewModel() {

private var _timeText: MutableStateFlow<String> = MutableStateFlow("")
val timeText = _timeText.asStateFlow()

fun updateResponse(dateFormat: DateFormat?, date: Date) {
dateFormat?.let {
_timeText.value = it.format(date)
setValue(fromMillis(date.time))
}
dateFormat?.let { setValue(fromMillis(date.time)) }
}
}
5 changes: 1 addition & 4 deletions ground/src/main/res/layout/date_task_frag.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@
xmlns:tools="http://schemas.android.com/tools">

<data>
<variable
name="viewModel"
type="com.google.android.ground.ui.datacollection.tasks.date.DateTaskViewModel" />
<variable
name="fragment"
type="com.google.android.ground.ui.datacollection.tasks.date.DateTaskFragment" />
Expand All @@ -44,7 +41,7 @@
android:inputType="datetime"
android:maxLines="1"
android:onClick="@{__ -> fragment.showDateDialog()}"
android:text="@{viewModel.dateText}"
android:text="@{fragment.dateText}"
tools:text="@string/date" />
</com.google.android.material.textfield.TextInputLayout>
</layout>
5 changes: 1 addition & 4 deletions ground/src/main/res/layout/time_task_frag.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@
xmlns:tools="http://schemas.android.com/tools">

<data>
<variable
name="viewModel"
type="com.google.android.ground.ui.datacollection.tasks.time.TimeTaskViewModel" />
<variable
name="fragment"
type="com.google.android.ground.ui.datacollection.tasks.time.TimeTaskFragment" />
Expand All @@ -44,7 +41,7 @@
android:inputType="datetime"
android:maxLines="1"
android:onClick="@{__ -> fragment.showTimeDialog()}"
android:text="@{viewModel.timeText}"
android:text="@{fragment.timeText}"
tools:text="@string/time" />
</com.google.android.material.textfield.TextInputLayout>
</layout>

This file was deleted.

This file was deleted.

0 comments on commit 3b2fab4

Please sign in to comment.