Skip to content

Commit

Permalink
add daily goals visible on type cards on main tab
Browse files Browse the repository at this point in the history
  • Loading branch information
Razeeman committed Oct 23, 2023
1 parent 7cbbbc7 commit 8092ef2
Show file tree
Hide file tree
Showing 24 changed files with 247 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class ChartFilterViewDataInteractor @Inject constructor(
isFiltered = type.id in typeIdsFiltered,
numberOfCards = numberOfCards,
isDarkTheme = isDarkTheme,
isChecked = null,
)
}
.takeUnless { it.isEmpty() }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.example.util.simpletimetracker.core.interactor

import com.example.util.simpletimetracker.domain.mapper.RangeMapper
import com.example.util.simpletimetracker.core.mapper.TimeMapper
import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor
import com.example.util.simpletimetracker.domain.interactor.RecordInteractor
import com.example.util.simpletimetracker.domain.mapper.RangeMapper
import com.example.util.simpletimetracker.domain.model.Range
import com.example.util.simpletimetracker.domain.model.RangeLength
import com.example.util.simpletimetracker.domain.model.Record
import com.example.util.simpletimetracker.domain.model.RecordType
import com.example.util.simpletimetracker.domain.model.RunningRecord
import java.lang.Long.max
import javax.inject.Inject
Expand All @@ -18,27 +20,68 @@ class GetCurrentRecordsDurationInteractor @Inject constructor(
) {

suspend fun getDailyCurrent(runningRecord: RunningRecord): Result {
return getRangeCurrent(runningRecord, getRange(RangeLength.Day))
return getRangeCurrent(runningRecord.id, runningRecord, getRange(RangeLength.Day))
}

suspend fun getWeeklyCurrent(runningRecord: RunningRecord): Result {
return getRangeCurrent(runningRecord, getRange(RangeLength.Week))
return getRangeCurrent(runningRecord.id, runningRecord, getRange(RangeLength.Week))
}

suspend fun getMonthlyCurrent(runningRecord: RunningRecord): Result {
return getRangeCurrent(runningRecord, getRange(RangeLength.Month))
return getRangeCurrent(runningRecord.id, runningRecord, getRange(RangeLength.Month))
}

suspend fun getAllDailyCurrents(
typesMap: Map<Long, RecordType>,
runningRecords: List<RunningRecord>,
): Map<Long, Result> {
val range = getRange(RangeLength.Day)
val rangeRecords = recordInteractor.getFromRange(range)

return typesMap.map { (typeId, type) ->
typeId to getRangeCurrent(
typeId = typeId,
runningRecord = runningRecords.firstOrNull { it.id == typeId },
range = range,
rangeRecords = rangeRecords,
)
}.toMap()
}

private suspend fun getRangeCurrent(
runningRecord: RunningRecord,
range: Range
typeId: Long,
runningRecord: RunningRecord?,
range: Range,
): Result {
return getRangeCurrent(
typeId = typeId,
runningRecord = runningRecord,
range = range,
rangeRecords = recordInteractor.getFromRange(range),
)
}

private fun getRangeCurrent(
typeId: Long,
runningRecord: RunningRecord?,
range: Range,
rangeRecords: List<Record>,
): Result {
val current = System.currentTimeMillis()
val currentRunning = current - runningRecord.timeStarted
val currentRunningClamped = current - max(runningRecord.timeStarted, range.timeStarted)
val currentRunning = if (runningRecord != null) {
current - runningRecord.timeStarted
} else {
0
}
val currentRunningClamped = if (runningRecord != null) {
current - max(runningRecord.timeStarted, range.timeStarted)
} else {
0
}
val currentRunningCount = if (runningRecord != null) 1 else 0

val records = recordInteractor.getFromRange(range)
.filter { it.typeId == runningRecord.id }
val records = rangeRecords
.filter { it.typeId == typeId }
.map { rangeMapper.clampToRange(it, range) }
val duration = records
.let(rangeMapper::mapToDuration)
Expand All @@ -47,8 +90,8 @@ class GetCurrentRecordsDurationInteractor @Inject constructor(
return Result(
range = range,
duration = duration + currentRunningClamped,
count = count + 1, // 1 is for current running record.
durationDiffersFromCurrent = duration != 0L || currentRunning != currentRunningClamped
count = count + currentRunningCount,
durationDiffersFromCurrent = duration != 0L || currentRunning != currentRunningClamped,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import javax.inject.Inject
class RecordTypesViewDataInteractor @Inject constructor(
private val prefsInteractor: PrefsInteractor,
private val recordTypeInteractor: RecordTypeInteractor,
private val recordTypeViewDataMapper: RecordTypeViewDataMapper
private val recordTypeViewDataMapper: RecordTypeViewDataMapper,
) {

suspend fun getTypesViewData(): List<ViewHolderType> {
Expand All @@ -19,7 +19,14 @@ class RecordTypesViewDataInteractor @Inject constructor(
return recordTypeInteractor.getAll()
.filter { !it.hidden }
.takeUnless { it.isEmpty() }
?.map { recordTypeViewDataMapper.map(it, numberOfCards, isDarkTheme) }
?.map {
recordTypeViewDataMapper.map(
recordType = it,
numberOfCards = numberOfCards,
isDarkTheme = isDarkTheme,
isChecked = null,
)
}
?: recordTypeViewDataMapper.mapToEmpty()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@ package com.example.util.simpletimetracker.core.mapper
import androidx.annotation.ColorInt
import androidx.annotation.StringRes
import com.example.util.simpletimetracker.core.R
import com.example.util.simpletimetracker.core.interactor.GetCurrentRecordsDurationInteractor
import com.example.util.simpletimetracker.core.repo.ResourceRepo
import com.example.util.simpletimetracker.domain.extension.getDaily
import com.example.util.simpletimetracker.domain.extension.orZero
import com.example.util.simpletimetracker.domain.extension.value
import com.example.util.simpletimetracker.domain.model.AppColor
import com.example.util.simpletimetracker.domain.model.RecordType
import com.example.util.simpletimetracker.domain.model.RecordTypeGoal
import com.example.util.simpletimetracker.feature_base_adapter.ViewHolderType
import com.example.util.simpletimetracker.feature_base_adapter.empty.EmptyViewData
import com.example.util.simpletimetracker.feature_base_adapter.recordType.RecordTypeViewData
Expand All @@ -17,32 +22,33 @@ class RecordTypeViewDataMapper @Inject constructor(
private val iconMapper: IconMapper,
private val colorMapper: ColorMapper,
private val resourceRepo: ResourceRepo,
private val recordTypeCardSizeMapper: RecordTypeCardSizeMapper
private val recordTypeCardSizeMapper: RecordTypeCardSizeMapper,
) {

fun mapToEmpty(): List<ViewHolderType> {
return EmptyViewData(
message = resourceRepo.getString(R.string.record_types_empty)
message = resourceRepo.getString(R.string.record_types_empty),
).let(::listOf)
}

fun map(
recordType: RecordType,
isDarkTheme: Boolean
isDarkTheme: Boolean,
): RecordTypeViewData {
return RecordTypeViewData(
id = recordType.id,
name = recordType.name,
iconId = iconMapper.mapIcon(recordType.icon),
iconColor = colorMapper.toIconColor(isDarkTheme),
color = mapColor(recordType.color, isDarkTheme)
color = mapColor(recordType.color, isDarkTheme),
)
}

fun map(
recordType: RecordType,
numberOfCards: Int,
isDarkTheme: Boolean
isDarkTheme: Boolean,
isChecked: Boolean?,
): RecordTypeViewData {
return RecordTypeViewData(
id = recordType.id,
Expand All @@ -52,17 +58,24 @@ class RecordTypeViewDataMapper @Inject constructor(
color = mapColor(recordType.color, isDarkTheme),
width = recordTypeCardSizeMapper.toCardWidth(numberOfCards),
height = recordTypeCardSizeMapper.toCardHeight(numberOfCards),
asRow = recordTypeCardSizeMapper.toCardAsRow(numberOfCards)
asRow = recordTypeCardSizeMapper.toCardAsRow(numberOfCards),
isChecked = isChecked,
)
}

fun mapFiltered(
recordType: RecordType,
numberOfCards: Int,
isDarkTheme: Boolean,
isFiltered: Boolean
isFiltered: Boolean,
isChecked: Boolean?,
): RecordTypeViewData {
val default = map(recordType, numberOfCards, isDarkTheme)
val default = map(
recordType = recordType,
numberOfCards = numberOfCards,
isDarkTheme = isDarkTheme,
isChecked = isChecked,
)

return if (isFiltered) {
default.copy(
Expand Down Expand Up @@ -114,6 +127,28 @@ class RecordTypeViewDataMapper @Inject constructor(
)
}

fun mapGoalCheckmark(
type: RecordType,
goals: Map<Long, List<RecordTypeGoal>>,
allDailyCurrents: Map<Long, GetCurrentRecordsDurationInteractor.Result>,
): Boolean? {
val goal = goals[type.id].orEmpty().getDaily()
val goalValue = when (goal?.type) {
is RecordTypeGoal.Type.Duration -> goal.value * 1000
is RecordTypeGoal.Type.Count -> goal.value
else -> 0
}
val dailyCurrent = allDailyCurrents[type.id]
val current = when (goal?.type) {
is RecordTypeGoal.Type.Duration -> dailyCurrent?.duration.orZero()
is RecordTypeGoal.Type.Count -> dailyCurrent?.count.orZero()
else -> 0
}
val valueLeft = goalValue - current

return if (goal != null) valueLeft <= 0L else null
}

private fun mapToSpecial(
type: RunningRecordTypeSpecialViewData.Type,
@StringRes name: Int,
Expand All @@ -132,7 +167,8 @@ class RecordTypeViewDataMapper @Inject constructor(
)
}

@ColorInt private fun mapColor(color: AppColor, isDarkTheme: Boolean): Int {
@ColorInt
private fun mapColor(color: AppColor, isDarkTheme: Boolean): Int {
return colorMapper.mapToColorInt(color, isDarkTheme)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ class ArchiveViewDataInteractor @Inject constructor(
recordType = type,
numberOfCards = numberOfCards,
isDarkTheme = isDarkTheme,
isFiltered = false
isFiltered = false,
isChecked = null,
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.example.util.simpletimetracker.feature_base_adapter.recordType

import androidx.core.view.ViewCompat
import com.example.util.simpletimetracker.domain.extension.orFalse
import com.example.util.simpletimetracker.feature_base_adapter.createRecyclerBindingAdapterDelegate
import com.example.util.simpletimetracker.feature_views.TransitionNames
import com.example.util.simpletimetracker.feature_views.extension.dpToPx
Expand Down Expand Up @@ -32,6 +33,8 @@ fun createRecordTypeAdapterDelegate(
itemIconColor = item.iconColor
itemIconAlpha = item.iconAlpha
itemName = item.name
itemWithCheck = item.isChecked != null
itemIsChecked = item.isChecked.orFalse()
onItemClick?.let { setOnClickWith(item, it) }
onItemLongClick?.let { setOnLongClick { it(item, mapOf(this to transitionName)) } }
if (withTransition) ViewCompat.setTransitionName(this, transitionName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ data class RecordTypeViewData(
@ColorInt val color: Int,
val width: Int? = null,
val height: Int? = null,
val asRow: Boolean = false
val asRow: Boolean = false,
val isChecked: Boolean? = null,
) : ViewHolderType {

override fun getUniqueId(): Long = id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ class ChangeActivityFilterViewDataInteractor @Inject constructor(
it.id to recordTypeViewDataMapper.map(
recordType = it,
numberOfCards = numberOfCards,
isDarkTheme = isDarkTheme
isDarkTheme = isDarkTheme,
isChecked = null,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ class ChangeCategoryViewDataInteractor @Inject constructor(
recordTypeViewDataMapper.map(
recordType = it,
numberOfCards = numberOfCards,
isDarkTheme = isDarkTheme
isDarkTheme = isDarkTheme,
isChecked = null,
)
}.let(viewData::addAll)

Expand All @@ -51,7 +52,8 @@ class ChangeCategoryViewDataInteractor @Inject constructor(
recordTypeViewDataMapper.map(
recordType = it,
numberOfCards = numberOfCards,
isDarkTheme = isDarkTheme
isDarkTheme = isDarkTheme,
isChecked = null,
)
}.let(viewData::addAll)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class DataEditTypeSelectionViewModel @Inject constructor(
recordType = type,
numberOfCards = numberOfCards,
isDarkTheme = isDarkTheme,
isChecked = null,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ class ArchiveDialogViewDataInteractor @Inject constructor(
val item = recordTypeViewDataMapper.map(
recordType = type,
numberOfCards = numberOfCards,
isDarkTheme = isDarkTheme
isDarkTheme = isDarkTheme,
isChecked = null,
)
val recordsCount = recordInteractor.getByType(listOf(typeId)).size
val recordTagCount = recordTagInteractor.getByType(typeId).size
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import javax.inject.Inject
class CardOrderViewModel @Inject constructor(
private val recordTypeInteractor: RecordTypeInteractor,
private val prefsInteractor: PrefsInteractor,
private val recordTypeViewDataMapper: RecordTypeViewDataMapper
private val recordTypeViewDataMapper: RecordTypeViewDataMapper,
) : ViewModel() {

lateinit var extra: CardOrderDialogParams
Expand Down Expand Up @@ -58,7 +58,14 @@ class CardOrderViewModel @Inject constructor(
return recordTypeInteractor.getAll(extra.initialOrder)
.filter { !it.hidden }
.takeUnless { it.isEmpty() }
?.map { type -> recordTypeViewDataMapper.map(type, numberOfCards, isDarkTheme) }
?.map { type ->
recordTypeViewDataMapper.map(
recordType = type,
numberOfCards = numberOfCards,
isDarkTheme = isDarkTheme,
isChecked = null,
)
}
?: recordTypeViewDataMapper.mapToEmpty()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@ class CardSizeViewDataMapper @Inject constructor(
numberOfCards: Int,
isDarkTheme: Boolean
): RecordTypeViewData {
return recordTypeViewDataMapper.map(recordType, numberOfCards, isDarkTheme)
return recordTypeViewDataMapper.map(
recordType = recordType,
numberOfCards = numberOfCards,
isDarkTheme = isDarkTheme,
isChecked = null,
)
}

fun toToButtonsViewData(numberOfCards: Int): List<ViewHolderType> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ class DefaultTypesSelectionViewModel @Inject constructor(
recordType = recordType,
numberOfCards = numberOfCards,
isDarkTheme = isDarkTheme,
isFiltered = recordType.id in typeIdsFiltered
isFiltered = recordType.id in typeIdsFiltered,
isChecked = null,
)
}
}
Expand Down
Loading

0 comments on commit 8092ef2

Please sign in to comment.