Skip to content

Commit

Permalink
fixed empty state displaying on initial load bug
Browse files Browse the repository at this point in the history
update versionName to 1.1.5
  • Loading branch information
llopisdon committed Mar 24, 2022
1 parent 0a3d6fe commit d3eaa6e
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 59 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ android {
minSdkVersion 22
targetSdkVersion 31
versionCode 1
versionName "1.1.4"
versionName "1.1.5"

def apodApiKey = localProperties["nasa_apod_api_key"] ?: 'DEMO_KEY'
println("APOD KEY: $apodApiKey")
Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/com/machineinteractive/apodktm/Apod.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Converters {
.date
}
}

@TypeConverter
fun localDateToTimestamp(date: LocalDate?): Long? {
val tz = TimeZone.currentSystemDefault()
Expand Down
31 changes: 24 additions & 7 deletions app/src/main/java/com/machineinteractive/apodktm/ApodDao.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package com.machineinteractive.apodktm

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import android.util.Log
import androidx.room.*
import kotlinx.coroutines.flow.Flow
import kotlinx.datetime.LocalDate
import kotlinx.datetime.*

@Dao
interface ApodDao {
Expand All @@ -18,12 +16,31 @@ interface ApodDao {
suspend fun getApodsCount(startDate: LocalDate, endDate: LocalDate): Int

@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insertApods(apods: List<Apod>)
suspend fun _insertApods(apods: List<Apod>)

@Query("SELECT * FROM lastupdate WHERE id = :id")
suspend fun getLastUpdate(id: String): LastUpdate?
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun setLastUpdate(lastUpdate: LastUpdate)
suspend fun _setLastUpdate(lastUpdate: LastUpdate)
@Query("SELECT * FROM apod WHERE date = :date")
suspend fun getApodForDay(date: LocalDate): Apod?

@Transaction
suspend fun insertApods(apods: List<Apod>, lastUpdateId: String) {
val timestamp = if (apods.isEmpty()) {
0L
} else {
Clock.System.now().toEpochMilliseconds()
}

Log.d(
TAG,
"\tHAS APODS: ${!apods.isEmpty()} num APODS: ${apods.count()} | set last update - id: $lastUpdateId timestamp: ${
Instant.fromEpochMilliseconds(timestamp)
.toLocalDateTime(TimeZone.currentSystemDefault())
}"
)
_insertApods(apods)
_setLastUpdate(LastUpdate(lastUpdateId, timestamp))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverters

@Database(entities = [ Apod::class, LastUpdate::class ], version = 1)
@Database(entities = [Apod::class, LastUpdate::class], version = 1)
@TypeConverters(Converters::class)
abstract class ApodDatabase : RoomDatabase() {
abstract fun apodDao(): ApodDao
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ class ApodDetailFragment : Fragment() {
apodDateCopyright.text = if (apod.copyright.isNullOrEmpty()) {
"${apod.date}"
} else {
"${apod.date} ${"(" + apod.copyright + ")" ?: ""}"
"${apod.date} (${apod.copyright})"
}

apodExplanation.text = apod.explanation
Expand All @@ -189,7 +189,11 @@ class ApodDetailFragment : Fragment() {
val intent = Intent(Intent.ACTION_VIEW, webpage)
startActivity(intent)
} catch (e: Exception) {
Toast.makeText(requireContext().applicationContext, R.string.no_video_player_found, Toast.LENGTH_SHORT).show()
Toast.makeText(
requireContext().applicationContext,
R.string.no_video_player_found,
Toast.LENGTH_SHORT
).show()
}
}

Expand Down
38 changes: 17 additions & 21 deletions app/src/main/java/com/machineinteractive/apodktm/ApodRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class ApodRepository(private val apodDao: ApodDao) {
}

fun getApodsForCurMonth(date: LocalDate): Flow<List<Apod>> {
Log.d(TAG, "getApodsForCurMonth: $date")
val (startDate, endDate) = getStartEndRangeForDate(date)
return apodDao.getApods(startDate, endDate)
}
Expand All @@ -59,25 +60,9 @@ class ApodRepository(private val apodDao: ApodDao) {

Log.d(TAG, "updateApodsForCurMonth\n\tstartDate: $startDate | enddate: $endDate")
val (apods, result) = fetchApods(startDate, endDate)
val lastUpdateId = getLastUpdateId(endDate)
apodDao.insertApods(apods, lastUpdateId)

apodDao.insertApods(apods)

val id = getLastUpdateId(endDate)
val timestamp = if (apods.isEmpty()) {
0L
} else {
Clock.System.now().toEpochMilliseconds()
}

Log.d(
TAG,
"\tHAS APODS: ${apods.isEmpty()} | set last update - id: $id timestamp: ${
Instant.fromEpochMilliseconds(timestamp)
.toLocalDateTime(TimeZone.currentSystemDefault())
}"
)

apodDao.setLastUpdate(LastUpdate(id, timestamp))
return result
}

Expand Down Expand Up @@ -186,6 +171,9 @@ class ApodRepository(private val apodDao: ApodDao) {
private fun getLastUpdateId(date: LocalDate): String =
"apod_${date.year}_${date.monthNumber}"

suspend fun lastUpdate(date: LocalDate): LastUpdate? =
apodDao.getLastUpdate(getLastUpdateId(date))

suspend fun needsUpdate(date: LocalDate): Boolean {

val id = getLastUpdateId(date)
Expand Down Expand Up @@ -225,12 +213,20 @@ class ApodRepository(private val apodDao: ApodDao) {
val lastApod = apodDao.getApodForDay(lastDayOfMonthForDate)

val nextMonthForDate = lastDayOfMonthForDate.plus(1, DateTimeUnit.DAY).atStartOfDayIn(
TimeZone.currentSystemDefault())
TimeZone.currentSystemDefault()
)
val timeStampInstant = Instant.fromEpochMilliseconds(lastUpdate.timestamp)
val secondsUntil = timeStampInstant.until(nextMonthForDate, DateTimeUnit.SECOND, TimeZone.currentSystemDefault())
val secondsUntil = timeStampInstant.until(
nextMonthForDate,
DateTimeUnit.SECOND,
TimeZone.currentSystemDefault()
)

if (secondsUntil > 0 && lastApod == null) {
Log.d(TAG, "needsUpdate: true - sec: $secondsUntil | PREV MONTH NEEDS ONE LAST CHECK FOR APODS")
Log.d(
TAG,
"needsUpdate: true - sec: $secondsUntil | PREV MONTH NEEDS ONE LAST CHECK FOR APODS"
)
return true
} else {
Log.d(TAG, "needsUpdate: false - PREV MONTH UP-TO-DATE")
Expand Down
33 changes: 24 additions & 9 deletions app/src/main/java/com/machineinteractive/apodktm/ApodViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ class ApodViewModel @Inject constructor(private val repository: ApodRepository)

private val curDate = MutableStateFlow(maxDate)
private var pickerCurDate = maxDate
@ExperimentalCoroutinesApi

@OptIn(ExperimentalCoroutinesApi::class)
private val apods: Flow<List<Apod>> = curDate.flatMapLatest {
repository.getApodsForCurMonth(it)
}

private val _apodListUiState = MutableStateFlow(ApodListUiState())
private val _apodListUiState = MutableStateFlow(ApodListUiState(loading = true))
val apodListUiState: StateFlow<ApodListUiState> = _apodListUiState

private val _selectedApod: MutableStateFlow<Apod?> = MutableStateFlow(null)
Expand All @@ -47,31 +48,44 @@ class ApodViewModel @Inject constructor(private val repository: ApodRepository)
_selectedApod.value = apod
}

var curJob: Job? = null
private var curJob: Job? = null

fun fetchApods() {
Log.d(TAG, "ApodViewModel.fetchApods - curDate: ${curDate.value} ...")

curJob = viewModelScope.launch(Dispatchers.IO) {

Log.d(TAG, "ApodViewModel.fetchApods - curDate: ${curDate.value} ...")

if (!isActive) return@launch

_apodListUiState.value = _apodListUiState.value.copy(error = null)
_apodListUiState.value = _apodListUiState.value.copy(error = null, lastUpdate = null)

val needsUpdate = repository.needsUpdate(curDate.value)
Log.d(TAG, "NEEDS UPDATE -> $needsUpdate")

if (repository.needsUpdate(curDate.value)) {
if (needsUpdate) {
if (!isActive) return@launch
var hasApods = repository.curMonthHasApods(curDate.value)
val hasApods = repository.curMonthHasApods(curDate.value)
Log.d(TAG, "hasApods: $hasApods")
if (!hasApods) {
_apodListUiState.value = _apodListUiState.value.copy(loading = true)
}
when (val result = repository.updateApodsForCurMonth(curDate.value)) {
is ApodResult.Error -> {
_apodListUiState.value = _apodListUiState.value.copy(error = result, loading = false)
_apodListUiState.value = _apodListUiState.value.copy(
error = result,
loading = false
)
return@launch
}
else -> {
// NO-OP
}
}
}

_apodListUiState.value = _apodListUiState.value.copy(loading = false)
val lastUpdate = repository.lastUpdate(curDate.value)
_apodListUiState.value = _apodListUiState.value.copy(lastUpdate = lastUpdate, loading = false)
}
}

Expand Down Expand Up @@ -195,6 +209,7 @@ data class PickerUiState(val today: LocalDate, val curPickerDate: LocalDate)

data class ApodListUiState(
val loading: Boolean = false,
val lastUpdate: LastUpdate? = null,
val error: ApodResult.Error? = null,
val apods: List<Apod> = emptyList()
)
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class ApodsListFragment : Fragment(), ApodAdapter.Listener {
adapter = ApodAdapter(this)

val isWideScreen = resources.getBoolean(R.bool.wide_screen)
val isLandscape = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
val isLandscape = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
val useGridLayout = isLandscape || isWideScreen

binding.run {
Expand Down Expand Up @@ -96,6 +96,7 @@ class ApodsListFragment : Fragment(), ApodAdapter.Listener {
}

private fun updateUi(state: ApodListUiState) {

showProgressBar(state.loading)

if (state.error != null) {
Expand All @@ -114,7 +115,7 @@ class ApodsListFragment : Fragment(), ApodAdapter.Listener {

adapter.submitList(state.apods)

val isEmpty = !state.loading && state.apods.isEmpty()
val isEmpty = state.lastUpdate != null && state.apods.isEmpty()
toggleEmptyState(isEmpty)
}

Expand Down Expand Up @@ -176,7 +177,12 @@ class ApodAdapter(private val listener: ApodAdapter.Listener) :
binding.title.text = "${apod.title}"
binding.date.text = "${apod.date}"

binding.image.setImageDrawable(ContextCompat.getDrawable(itemView.context, R.drawable.donald_giannatti_very_large_array_socorro_usa_unsplash_1232x820_blur))
binding.image.setImageDrawable(
ContextCompat.getDrawable(
itemView.context,
R.drawable.donald_giannatti_very_large_array_socorro_usa_unsplash_1232x820_blur
)
)

val (imageUrl, videoIndicatorVisibility) = if (apod.media_type == "image") {
Pair(apod.url.orEmpty(), View.INVISIBLE)
Expand All @@ -195,7 +201,7 @@ class ApodAdapter(private val listener: ApodAdapter.Listener) :
binding.image.setImageDrawable(result)
binding.apod.isClickable = true
binding.apod.isCheckable = true
},onError = {
}, onError = {
binding.apod.isClickable = true
binding.apod.isCheckable = true
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ class NavOverlayFragment : Fragment(), NavController.OnDestinationChangedListene
}
launch {
viewModel.bottomNavBarUiState.collect { state ->
with (bottomNavBar) {
with(bottomNavBar) {
prevMonthButton.apply {
if (state.prevMonthEnabled) show() else hide()
}
Expand All @@ -171,15 +171,17 @@ class NavOverlayFragment : Fragment(), NavController.OnDestinationChangedListene
}
}
}
}}
}
}
}

private fun setupPickerViews(curPickerDate: LocalDate) {

with(binding.monthYearPicker) {

val curYear = curPickerDate.year
val curMonthText = resources.getStringArray(R.array.months)[curPickerDate.monthNumber-1]
val curMonthText =
resources.getStringArray(R.array.months)[curPickerDate.monthNumber - 1]

curMonthYear.text = resources.getString(R.string.cur_month_year, curMonthText, curYear)

Expand All @@ -205,13 +207,14 @@ class NavOverlayFragment : Fragment(), NavController.OnDestinationChangedListene
}
}

(monthChips[curPickerDate.monthNumber-1] as Chip).isChecked = true
(monthChips[curPickerDate.monthNumber - 1] as Chip).isChecked = true
}
}

private fun setBottomNavBarMonthButtonText(today: LocalDate) {
val curMonthText = resources.getStringArray(R.array.months)[today.monthNumber-1]
binding.bottomNavBar.monthButton.text = resources.getString(R.string.cur_month_year, curMonthText, today.year)
val curMonthText = resources.getStringArray(R.array.months)[today.monthNumber - 1]
binding.bottomNavBar.monthButton.text =
resources.getString(R.string.cur_month_year, curMonthText, today.year)
}

private fun openPicker() {
Expand Down Expand Up @@ -247,16 +250,25 @@ class NavOverlayFragment : Fragment(), NavController.OnDestinationChangedListene
) {
when (destination.id) {
R.id.apodsListFragment -> {
ObjectAnimator.ofFloat(binding.bottomNavBar.bottomNavBar, "translationY", 0f).apply {
duration = resources.getInteger(R.integer.material_transition_duration_medium).toLong()
interpolator = DecelerateInterpolator()
start()
}
ObjectAnimator.ofFloat(binding.bottomNavBar.bottomNavBar, "translationY", 0f)
.apply {
duration =
resources.getInteger(R.integer.material_transition_duration_medium)
.toLong()
interpolator = DecelerateInterpolator()
start()
}
}
R.id.apodDetailFragment -> {
val bottomNavHeight = resources.getDimensionPixelSize(R.dimen.bottom_nav_bar_height).toFloat()
ObjectAnimator.ofFloat(binding.bottomNavBar.bottomNavBar, "translationY", bottomNavHeight).apply {
duration = resources.getInteger(R.integer.material_transition_duration_medium).toLong()
val bottomNavHeight =
resources.getDimensionPixelSize(R.dimen.bottom_nav_bar_height).toFloat()
ObjectAnimator.ofFloat(
binding.bottomNavBar.bottomNavBar,
"translationY",
bottomNavHeight
).apply {
duration =
resources.getInteger(R.integer.material_transition_duration_medium).toLong()
interpolator = FastOutLinearInInterpolator()
start()
}
Expand Down

0 comments on commit d3eaa6e

Please sign in to comment.