From db65d8216713f401c53933154224460e89dc39b3 Mon Sep 17 00:00:00 2001 From: razeeman Date: Sun, 15 Dec 2024 17:30:13 +0300 Subject: [PATCH] add goal type for limits --- .../data_local/backup/BackupRepoImpl.kt | 21 ++- .../data_local/database/AppDatabase.kt | 2 +- .../database/AppDatabaseMigrations.kt | 10 ++ .../recordType/RecordTypeGoalDBO.kt | 5 + .../RecordTypeGoalDataLocalMapper.kt | 9 ++ .../domain/model/RecordTypeGoal.kt | 15 ++- .../api/ChangeRecordTypeGoalsViewData.kt | 6 +- .../api/GoalsViewModelDelegate.kt | 2 + .../delegate/GoalsViewModelDelegateImpl.kt | 124 +++++++++++------- .../mapper/GoalsViewDataMapper.kt | 44 +++++-- .../ChangeRecordTypeGoalSubtypeViewData.kt | 16 +++ .../viewData/ChangeRecordTypeGoalsState.kt | 16 ++- .../views/GoalsViewDelegate.kt | 10 ++ .../main/res/layout/change_goal_layout.xml | 9 +- resources/src/main/res/values-ar/strings.xml | 1 + resources/src/main/res/values-ca/strings.xml | 1 + resources/src/main/res/values-de/strings.xml | 1 + resources/src/main/res/values-es/strings.xml | 1 + resources/src/main/res/values-fa/strings.xml | 1 + resources/src/main/res/values-fr/strings.xml | 1 + resources/src/main/res/values-hi/strings.xml | 1 + resources/src/main/res/values-in/strings.xml | 1 + resources/src/main/res/values-it/strings.xml | 1 + resources/src/main/res/values-iw/strings.xml | 1 + resources/src/main/res/values-ja/strings.xml | 1 + resources/src/main/res/values-ko/strings.xml | 1 + resources/src/main/res/values-nl/strings.xml | 1 + resources/src/main/res/values-pl/strings.xml | 1 + .../src/main/res/values-pt-rPT/strings.xml | 1 + resources/src/main/res/values-pt/strings.xml | 1 + resources/src/main/res/values-ro/strings.xml | 1 + resources/src/main/res/values-ru/strings.xml | 1 + resources/src/main/res/values-sv/strings.xml | 1 + resources/src/main/res/values-tr/strings.xml | 1 + resources/src/main/res/values-uk/strings.xml | 1 + resources/src/main/res/values-vi/strings.xml | 1 + .../src/main/res/values-zh-rTW/strings.xml | 1 + resources/src/main/res/values-zh/strings.xml | 1 + resources/src/main/res/values/strings.xml | 1 + 39 files changed, 239 insertions(+), 75 deletions(-) create mode 100644 features/feature_change_goals/src/main/java/com/example/util/simpletimetracker/feature_change_goals/viewData/ChangeRecordTypeGoalSubtypeViewData.kt diff --git a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/backup/BackupRepoImpl.kt b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/backup/BackupRepoImpl.kt index 9e952e9ed..669b2bb5c 100644 --- a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/backup/BackupRepoImpl.kt +++ b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/backup/BackupRepoImpl.kt @@ -505,11 +505,15 @@ class BackupRepoImpl @Inject constructor( is RecordTypeGoal.Type.Duration -> 0L is RecordTypeGoal.Type.Count -> 1L }.toString() + val subtypeString = when (recordTypeGoal.subType) { + is RecordTypeGoal.Subtype.Goal -> 0L + is RecordTypeGoal.Subtype.Limit -> 1L + }.toString() val daysOfWeekString = daysOfWeekDataLocalMapper .mapDaysOfWeek(recordTypeGoal.daysOfWeek) return String.format( - "$ROW_RECORD_TYPE_GOAL\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", + "$ROW_RECORD_TYPE_GOAL\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", recordTypeGoal.id.toString(), (recordTypeGoal.idData as? RecordTypeGoal.IdData.Type)?.value.orZero(), rangeString, @@ -517,6 +521,7 @@ class BackupRepoImpl @Inject constructor( recordTypeGoal.type.value.toString(), (recordTypeGoal.idData as? RecordTypeGoal.IdData.Category)?.value.orZero(), daysOfWeekString, + subtypeString, ) } @@ -550,7 +555,8 @@ class BackupRepoImpl @Inject constructor( val weeklyGoalTime = parts.getOrNull(9)?.toLongOrNull().orZero() val monthlyGoalTime = parts.getOrNull(10)?.toLongOrNull().orZero() // Didn't exist when goal time was in type db, no need to migrate. - val daysOfWeek = DayOfWeek.values().toList() + val daysOfWeek = DayOfWeek.entries + val subType = RecordTypeGoal.Subtype.Goal val goalTimes = mutableListOf().apply { if (goalTime != 0L) { @@ -559,6 +565,7 @@ class BackupRepoImpl @Inject constructor( idData = RecordTypeGoal.IdData.Type(typeId), range = RecordTypeGoal.Range.Session, type = RecordTypeGoal.Type.Duration(goalTime), + subType = subType, daysOfWeek = daysOfWeek, ).let(::add) } @@ -567,6 +574,7 @@ class BackupRepoImpl @Inject constructor( idData = RecordTypeGoal.IdData.Type(typeId), range = RecordTypeGoal.Range.Daily, type = RecordTypeGoal.Type.Duration(dailyGoalTime), + subType = subType, daysOfWeek = daysOfWeek, ).let(::add) } @@ -575,6 +583,7 @@ class BackupRepoImpl @Inject constructor( idData = RecordTypeGoal.IdData.Type(typeId), range = RecordTypeGoal.Range.Weekly, type = RecordTypeGoal.Type.Duration(weeklyGoalTime), + subType = subType, daysOfWeek = daysOfWeek, ).let(::add) } @@ -583,6 +592,7 @@ class BackupRepoImpl @Inject constructor( idData = RecordTypeGoal.IdData.Type(typeId), range = RecordTypeGoal.Range.Monthly, type = RecordTypeGoal.Type.Duration(monthlyGoalTime), + subType = subType, daysOfWeek = daysOfWeek, ).let(::add) } @@ -755,6 +765,13 @@ class BackupRepoImpl @Inject constructor( else -> RecordTypeGoal.Type.Duration(value) } }, + subType = run { + when (parts.getOrNull(8)?.toLongOrNull()) { + 0L -> RecordTypeGoal.Subtype.Goal + 1L -> RecordTypeGoal.Subtype.Limit + else -> RecordTypeGoal.Subtype.Goal + } + }, daysOfWeek = daysOfWeekDataLocalMapper.mapDaysOfWeek(daysOfWeekString), ) } diff --git a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/database/AppDatabase.kt b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/database/AppDatabase.kt index 98077716c..812d077a4 100644 --- a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/database/AppDatabase.kt +++ b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/database/AppDatabase.kt @@ -54,7 +54,7 @@ import com.example.util.simpletimetracker.data_local.recordType.RecordTypeGoalDa ComplexRuleDBO::class, FavouriteColorDBO::class, ], - version = 23, + version = 24, exportSchema = true, ) abstract class AppDatabase : RoomDatabase() { diff --git a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/database/AppDatabaseMigrations.kt b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/database/AppDatabaseMigrations.kt index 850606200..e7069520f 100644 --- a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/database/AppDatabaseMigrations.kt +++ b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/database/AppDatabaseMigrations.kt @@ -3,6 +3,7 @@ package com.example.util.simpletimetracker.data_local.database import androidx.room.migration.Migration import androidx.sqlite.db.SupportSQLiteDatabase +@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") class AppDatabaseMigrations { companion object { @@ -30,6 +31,7 @@ class AppDatabaseMigrations { migration_20_21, migration_21_22, migration_22_23, + migration_23_24, ) private val migration_1_2 = object : Migration(1, 2) { @@ -297,5 +299,13 @@ class AppDatabaseMigrations { ) } } + + private val migration_23_24 = object : Migration(23, 24) { + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL( + "ALTER TABLE recordTypeGoals ADD COLUMN goalType INTEGER NOT NULL DEFAULT 0", + ) + } + } } } \ No newline at end of file diff --git a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/recordType/RecordTypeGoalDBO.kt b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/recordType/RecordTypeGoalDBO.kt index fc5352907..bb246c259 100644 --- a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/recordType/RecordTypeGoalDBO.kt +++ b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/recordType/RecordTypeGoalDBO.kt @@ -25,6 +25,11 @@ data class RecordTypeGoalDBO( @ColumnInfo(name = "type") val type: Long, + // 0 - goal + // 1 - limit + @ColumnInfo(name = "goalType") + val subType: Long, + // seconds if goal time // count if goal count @ColumnInfo(name = "value") diff --git a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/recordType/RecordTypeGoalDataLocalMapper.kt b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/recordType/RecordTypeGoalDataLocalMapper.kt index ad51b717f..61959347f 100644 --- a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/recordType/RecordTypeGoalDataLocalMapper.kt +++ b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/recordType/RecordTypeGoalDataLocalMapper.kt @@ -29,6 +29,11 @@ class RecordTypeGoalDataLocalMapper @Inject constructor( 1L -> RecordTypeGoal.Type.Count(dbo.value) else -> RecordTypeGoal.Type.Duration(dbo.value) }, + subType = when (dbo.subType) { + 0L -> RecordTypeGoal.Subtype.Goal + 1L -> RecordTypeGoal.Subtype.Limit + else -> RecordTypeGoal.Subtype.Goal + }, daysOfWeek = daysOfWeekDataLocalMapper.mapDaysOfWeek(dbo.daysOfWeek), ) } @@ -47,6 +52,10 @@ class RecordTypeGoalDataLocalMapper @Inject constructor( is RecordTypeGoal.Type.Duration -> 0L is RecordTypeGoal.Type.Count -> 1L }, + subType = when (domain.subType) { + is RecordTypeGoal.Subtype.Goal -> 0L + is RecordTypeGoal.Subtype.Limit -> 1L + }, value = domain.type.value, categoryId = (domain.idData as? RecordTypeGoal.IdData.Category)?.value.orZero(), daysOfWeek = daysOfWeekDataLocalMapper.mapDaysOfWeek(domain.daysOfWeek), diff --git a/domain/src/main/java/com/example/util/simpletimetracker/domain/model/RecordTypeGoal.kt b/domain/src/main/java/com/example/util/simpletimetracker/domain/model/RecordTypeGoal.kt index af02f7f29..70cbedb14 100644 --- a/domain/src/main/java/com/example/util/simpletimetracker/domain/model/RecordTypeGoal.kt +++ b/domain/src/main/java/com/example/util/simpletimetracker/domain/model/RecordTypeGoal.kt @@ -5,6 +5,7 @@ data class RecordTypeGoal( val idData: IdData, val range: Range, val type: Type, + val subType: Subtype, val daysOfWeek: List, ) { @@ -15,12 +16,11 @@ data class RecordTypeGoal( data class Category(override val value: Long) : IdData } - // TODO switch to GoalTimeType sealed interface Range { - object Session : Range - object Daily : Range - object Weekly : Range - object Monthly : Range + data object Session : Range + data object Daily : Range + data object Weekly : Range + data object Monthly : Range } sealed interface Type { @@ -29,4 +29,9 @@ data class RecordTypeGoal( data class Duration(override val value: Long) : Type data class Count(override val value: Long) : Type } + + sealed interface Subtype { + data object Goal: Subtype + data object Limit: Subtype + } } \ No newline at end of file diff --git a/features/feature_change_goals/api/src/main/java/com/example/util/simpletimetracker/feature_change_goals/api/ChangeRecordTypeGoalsViewData.kt b/features/feature_change_goals/api/src/main/java/com/example/util/simpletimetracker/feature_change_goals/api/ChangeRecordTypeGoalsViewData.kt index 5a74f1973..3c32c1684 100644 --- a/features/feature_change_goals/api/src/main/java/com/example/util/simpletimetracker/feature_change_goals/api/ChangeRecordTypeGoalsViewData.kt +++ b/features/feature_change_goals/api/src/main/java/com/example/util/simpletimetracker/feature_change_goals/api/ChangeRecordTypeGoalsViewData.kt @@ -1,5 +1,6 @@ package com.example.util.simpletimetracker.feature_change_goals.api +import com.example.util.simpletimetracker.core.view.buttonsRowView.ButtonsRowViewData import com.example.util.simpletimetracker.feature_base_adapter.ViewHolderType import com.example.util.simpletimetracker.feature_views.spinner.CustomSpinner @@ -17,11 +18,12 @@ data class ChangeRecordTypeGoalsViewData( val typeItems: List, val typeSelectedPosition: Int, val type: Type, + val subtypeItems: List, val value: String, ) sealed interface Type { - object Duration : Type - object Count : Type + data object Duration : Type + data object Count : Type } } \ No newline at end of file diff --git a/features/feature_change_goals/api/src/main/java/com/example/util/simpletimetracker/feature_change_goals/api/GoalsViewModelDelegate.kt b/features/feature_change_goals/api/src/main/java/com/example/util/simpletimetracker/feature_change_goals/api/GoalsViewModelDelegate.kt index 0c16369f6..e8f7ef500 100644 --- a/features/feature_change_goals/api/src/main/java/com/example/util/simpletimetracker/feature_change_goals/api/GoalsViewModelDelegate.kt +++ b/features/feature_change_goals/api/src/main/java/com/example/util/simpletimetracker/feature_change_goals/api/GoalsViewModelDelegate.kt @@ -1,6 +1,7 @@ package com.example.util.simpletimetracker.feature_change_goals.api import androidx.lifecycle.LiveData +import com.example.util.simpletimetracker.core.view.buttonsRowView.ButtonsRowViewData import com.example.util.simpletimetracker.domain.model.RecordTypeGoal import com.example.util.simpletimetracker.feature_base_adapter.dayOfWeek.DayOfWeekViewData @@ -14,6 +15,7 @@ interface GoalsViewModelDelegate { fun onGoalDurationSet(tag: String?, duration: Long, anchor: Any) fun onGoalDurationDisabled(tag: String?) fun onGoalTypeSelected(range: RecordTypeGoal.Range, position: Int) + fun onGoalSubTypeSelected(range: RecordTypeGoal.Range, viewData: ButtonsRowViewData) fun onGoalCountChange(range: RecordTypeGoal.Range, count: String) fun onGoalTimeClick(range: RecordTypeGoal.Range) fun onDayOfWeekClick(data: DayOfWeekViewData) diff --git a/features/feature_change_goals/src/main/java/com/example/util/simpletimetracker/feature_change_goals/delegate/GoalsViewModelDelegateImpl.kt b/features/feature_change_goals/src/main/java/com/example/util/simpletimetracker/feature_change_goals/delegate/GoalsViewModelDelegateImpl.kt index e54fbfb5d..69c056c43 100644 --- a/features/feature_change_goals/src/main/java/com/example/util/simpletimetracker/feature_change_goals/delegate/GoalsViewModelDelegateImpl.kt +++ b/features/feature_change_goals/src/main/java/com/example/util/simpletimetracker/feature_change_goals/delegate/GoalsViewModelDelegateImpl.kt @@ -8,6 +8,7 @@ import com.example.util.simpletimetracker.core.extension.lazySuspend import com.example.util.simpletimetracker.core.extension.set import com.example.util.simpletimetracker.core.interactor.CheckExactAlarmPermissionInteractor import com.example.util.simpletimetracker.core.repo.PermissionRepo +import com.example.util.simpletimetracker.core.view.buttonsRowView.ButtonsRowViewData import com.example.util.simpletimetracker.domain.extension.getDaily import com.example.util.simpletimetracker.domain.extension.getMonthly import com.example.util.simpletimetracker.domain.extension.getSession @@ -22,6 +23,7 @@ import com.example.util.simpletimetracker.feature_change_goals.mapper.GoalsViewD import com.example.util.simpletimetracker.feature_change_goals.viewData.ChangeRecordTypeGoalsState import com.example.util.simpletimetracker.feature_change_goals.api.ChangeRecordTypeGoalsViewData import com.example.util.simpletimetracker.feature_change_goals.api.GoalsViewModelDelegate +import com.example.util.simpletimetracker.feature_change_goals.viewData.ChangeRecordTypeGoalSubtypeViewData import com.example.util.simpletimetracker.navigation.Router import com.example.util.simpletimetracker.navigation.params.action.OpenSystemSettings import com.example.util.simpletimetracker.navigation.params.screen.DurationDialogParams @@ -61,42 +63,39 @@ class GoalsViewModelDelegateImpl @Inject constructor( } override fun onGoalTypeSelected(range: RecordTypeGoal.Range, position: Int) { - val currentType = when (range) { - is RecordTypeGoal.Range.Session -> newGoalsState.session - is RecordTypeGoal.Range.Daily -> newGoalsState.daily - is RecordTypeGoal.Range.Weekly -> newGoalsState.weekly - is RecordTypeGoal.Range.Monthly -> newGoalsState.monthly - } val newType = goalsViewDataMapper.toGoalType(position) - if (currentType::class.java == newType::class.java) return + if (newGoalsState.getCurrentState(range).type::class.java == newType::class.java) return + newGoalsState = newGoalsState.change(range) { copy(type = newType) } + updateGoalsViewData() + } - newGoalsState = when (range) { - is RecordTypeGoal.Range.Session -> newGoalsState.copy(session = newType) - is RecordTypeGoal.Range.Daily -> newGoalsState.copy(daily = newType) - is RecordTypeGoal.Range.Weekly -> newGoalsState.copy(weekly = newType) - is RecordTypeGoal.Range.Monthly -> newGoalsState.copy(monthly = newType) - } + override fun onGoalSubTypeSelected(range: RecordTypeGoal.Range, viewData : ButtonsRowViewData) { + if (viewData !is ChangeRecordTypeGoalSubtypeViewData) return + val newSubType = viewData.subtype + if (newGoalsState.getCurrentState(range).subtype::class.java == newSubType::class.java) return + newGoalsState = newGoalsState.change(range) { copy(subtype = newSubType) } updateGoalsViewData() } override fun onGoalCountChange(range: RecordTypeGoal.Range, count: String) { - val currentGoal = when (range) { + val currentState = when (range) { is RecordTypeGoal.Range.Session -> newGoalsState.session is RecordTypeGoal.Range.Daily -> newGoalsState.daily is RecordTypeGoal.Range.Weekly -> newGoalsState.weekly is RecordTypeGoal.Range.Monthly -> newGoalsState.monthly } - val currentCount = (currentGoal as? RecordTypeGoal.Type.Count) + val currentCount = (currentState.type as? RecordTypeGoal.Type.Count) ?.value ?: return val newCount = count.toLongOrNull() if (currentCount != newCount) { val newType = RecordTypeGoal.Type.Count(newCount.orZero()) + val newState = currentState.copy(type = newType) newGoalsState = when (range) { - is RecordTypeGoal.Range.Session -> newGoalsState.copy(session = newType) - is RecordTypeGoal.Range.Daily -> newGoalsState.copy(daily = newType) - is RecordTypeGoal.Range.Weekly -> newGoalsState.copy(weekly = newType) - is RecordTypeGoal.Range.Monthly -> newGoalsState.copy(monthly = newType) + is RecordTypeGoal.Range.Session -> newGoalsState.copy(session = newState) + is RecordTypeGoal.Range.Daily -> newGoalsState.copy(daily = newState) + is RecordTypeGoal.Range.Weekly -> newGoalsState.copy(weekly = newState) + is RecordTypeGoal.Range.Monthly -> newGoalsState.copy(monthly = newState) } updateGoalsViewData() } @@ -120,7 +119,7 @@ class GoalsViewModelDelegateImpl @Inject constructor( DurationDialogParams( tag = tag, value = DurationDialogParams.Value.DurationSeconds( - duration = goalType.value.orZero(), + duration = goalType.type.value.orZero(), ), ), ) @@ -144,18 +143,21 @@ class GoalsViewModelDelegateImpl @Inject constructor( suspend fun processGoal( goalId: Long, - goalType: RecordTypeGoal.Type, + state: ChangeRecordTypeGoalsState.GoalState, goalRange: RecordTypeGoal.Range, daysOfWeek: List, ) { - if (goalType.value == 0L) { + val type = state.type + val goalType = state.subtype + if (type.value == 0L) { recordTypeGoalInteractor.remove(goalId) } else { RecordTypeGoal( id = goalId, idData = id, range = goalRange, - type = goalType, + type = type, + subType = goalType, daysOfWeek = daysOfWeek, ).let { recordTypeGoalInteractor.add(it) @@ -165,25 +167,25 @@ class GoalsViewModelDelegateImpl @Inject constructor( processGoal( goalId = goals.getSession()?.id.orZero(), - goalType = newGoalsState.session, + state = newGoalsState.session, goalRange = RecordTypeGoal.Range.Session, daysOfWeek = emptyList(), ) processGoal( goalId = goals.getDaily()?.id.orZero(), - goalType = newGoalsState.daily, + state = newGoalsState.daily, goalRange = RecordTypeGoal.Range.Daily, daysOfWeek = newGoalsState.daysOfWeek, ) processGoal( goalId = goals.getWeekly()?.id.orZero(), - goalType = newGoalsState.weekly, + state = newGoalsState.weekly, goalRange = RecordTypeGoal.Range.Weekly, daysOfWeek = emptyList(), ) processGoal( goalId = goals.getMonthly()?.id.orZero(), - goalType = newGoalsState.monthly, + state = newGoalsState.monthly, goalRange = RecordTypeGoal.Range.Monthly, daysOfWeek = emptyList(), ) @@ -195,35 +197,36 @@ class GoalsViewModelDelegateImpl @Inject constructor( val goals = getGoals(id) val defaultGoal = goalsViewDataMapper.getDefaultGoal() + fun mapState( + goal: RecordTypeGoal, + ): ChangeRecordTypeGoalsState.GoalState { + return ChangeRecordTypeGoalsState.GoalState( + type = goal.type, + subtype = goal.subType, + ) + } + newGoalsState = ChangeRecordTypeGoalsState( - session = goals.getSession()?.type ?: defaultGoal, - daily = goals.getDaily()?.type ?: defaultGoal, - weekly = goals.getWeekly()?.type ?: defaultGoal, - monthly = goals.getMonthly()?.type ?: defaultGoal, - daysOfWeek = goals.getDaily()?.daysOfWeek ?: DayOfWeek.values().toList(), + session = goals.getSession()?.let(::mapState) ?: defaultGoal, + daily = goals.getDaily()?.let(::mapState) ?: defaultGoal, + weekly = goals.getWeekly()?.let(::mapState) ?: defaultGoal, + monthly = goals.getMonthly()?.let(::mapState) ?: defaultGoal, + daysOfWeek = goals.getDaily()?.daysOfWeek ?: DayOfWeek.entries, ) updateGoalsViewData() } private fun onNewGoalDuration(tag: String?, duration: Long) { - val newType = RecordTypeGoal.Type.Duration(duration) - - when (tag) { - SESSION_GOAL_TIME_DIALOG_TAG -> { - newGoalsState = newGoalsState.copy(session = newType) - } - DAILY_GOAL_TIME_DIALOG_TAG -> { - newGoalsState = newGoalsState.copy(daily = newType) - } - WEEKLY_GOAL_TIME_DIALOG_TAG -> { - newGoalsState = newGoalsState.copy(weekly = newType) - } - MONTHLY_GOAL_TIME_DIALOG_TAG -> { - newGoalsState = newGoalsState.copy(monthly = newType) - } + val range = when (tag) { + SESSION_GOAL_TIME_DIALOG_TAG -> RecordTypeGoal.Range.Session + DAILY_GOAL_TIME_DIALOG_TAG -> RecordTypeGoal.Range.Daily + WEEKLY_GOAL_TIME_DIALOG_TAG -> RecordTypeGoal.Range.Weekly + MONTHLY_GOAL_TIME_DIALOG_TAG -> RecordTypeGoal.Range.Monthly + else -> return } - + val newType = RecordTypeGoal.Type.Duration(duration) + newGoalsState = newGoalsState.change(range) { copy(type = newType) } updateGoalsViewData() } @@ -234,6 +237,31 @@ class GoalsViewModelDelegateImpl @Inject constructor( } } + private fun ChangeRecordTypeGoalsState.getCurrentState( + range: RecordTypeGoal.Range + ): ChangeRecordTypeGoalsState.GoalState { + return when (range) { + is RecordTypeGoal.Range.Session -> session + is RecordTypeGoal.Range.Daily -> daily + is RecordTypeGoal.Range.Weekly -> weekly + is RecordTypeGoal.Range.Monthly -> monthly + } + } + + private fun ChangeRecordTypeGoalsState.change( + range: RecordTypeGoal.Range, + producer: ChangeRecordTypeGoalsState.GoalState.() -> ChangeRecordTypeGoalsState.GoalState, + ): ChangeRecordTypeGoalsState { + val currentState = getCurrentState(range) + val newState = currentState.producer() + return when (range) { + is RecordTypeGoal.Range.Session -> newGoalsState.copy(session = newState) + is RecordTypeGoal.Range.Daily -> newGoalsState.copy(daily = newState) + is RecordTypeGoal.Range.Weekly -> newGoalsState.copy(weekly = newState) + is RecordTypeGoal.Range.Monthly -> newGoalsState.copy(monthly = newState) + } + } + private fun updateGoalsViewData() = delegateScope.launch { val data = loadGoalsViewData() goalsViewData.set(data) diff --git a/features/feature_change_goals/src/main/java/com/example/util/simpletimetracker/feature_change_goals/mapper/GoalsViewDataMapper.kt b/features/feature_change_goals/src/main/java/com/example/util/simpletimetracker/feature_change_goals/mapper/GoalsViewDataMapper.kt index f9f99c8fa..472f7e389 100644 --- a/features/feature_change_goals/src/main/java/com/example/util/simpletimetracker/feature_change_goals/mapper/GoalsViewDataMapper.kt +++ b/features/feature_change_goals/src/main/java/com/example/util/simpletimetracker/feature_change_goals/mapper/GoalsViewDataMapper.kt @@ -3,6 +3,7 @@ package com.example.util.simpletimetracker.feature_change_goals.mapper import com.example.util.simpletimetracker.core.mapper.DayOfWeekViewDataMapper import com.example.util.simpletimetracker.core.mapper.TimeMapper import com.example.util.simpletimetracker.core.repo.ResourceRepo +import com.example.util.simpletimetracker.domain.extension.orEmpty import com.example.util.simpletimetracker.domain.extension.orZero import com.example.util.simpletimetracker.domain.model.DayOfWeek import com.example.util.simpletimetracker.domain.model.RecordTypeGoal @@ -11,6 +12,7 @@ import com.example.util.simpletimetracker.feature_base_adapter.dayOfWeek.DayOfWe import com.example.util.simpletimetracker.feature_change_goals.R import com.example.util.simpletimetracker.feature_change_goals.viewData.ChangeRecordTypeGoalsState import com.example.util.simpletimetracker.feature_change_goals.api.ChangeRecordTypeGoalsViewData +import com.example.util.simpletimetracker.feature_change_goals.viewData.ChangeRecordTypeGoalSubtypeViewData import com.example.util.simpletimetracker.feature_views.spinner.CustomSpinner import javax.inject.Inject @@ -46,29 +48,29 @@ class GoalsViewDataMapper @Inject constructor( goalsState.weekly, goalsState.monthly, ).count { - it.value > 0 + it.type.value > 0 } return ChangeRecordTypeGoalsViewData( selectedCount = selectedCount, session = mapGoalViewData( title = resourceRepo.getString(R.string.change_record_type_session_goal_time), - goal = goalsState.session, + state = goalsState.session, ), daily = mapGoalViewData( title = resourceRepo.getString(R.string.change_record_type_daily_goal_time), - goal = goalsState.daily, + state = goalsState.daily, ), weekly = mapGoalViewData( title = resourceRepo.getString(R.string.change_record_type_weekly_goal_time), - goal = goalsState.weekly, + state = goalsState.weekly, ), monthly = mapGoalViewData( title = resourceRepo.getString(R.string.change_record_type_monthly_goal_time), - goal = goalsState.monthly, + state = goalsState.monthly, ), daysOfWeek = mapDaysOfWeekViewData( - goal = goalsState.daily, + goal = goalsState.daily.type, selectedDaysOfWeek = goalsState.daysOfWeek, isDarkTheme = isDarkTheme, ), @@ -81,18 +83,22 @@ class GoalsViewDataMapper @Inject constructor( daily = getDefaultGoal(), weekly = getDefaultGoal(), monthly = getDefaultGoal(), - daysOfWeek = DayOfWeek.values().toList(), + daysOfWeek = DayOfWeek.entries, ) } - fun getDefaultGoal(): RecordTypeGoal.Type { - return RecordTypeGoal.Type.Duration(0) + fun getDefaultGoal(): ChangeRecordTypeGoalsState.GoalState { + return ChangeRecordTypeGoalsState.GoalState( + type = RecordTypeGoal.Type.Duration(0), + subtype = RecordTypeGoal.Subtype.Goal + ) } private fun mapGoalViewData( title: String, - goal: RecordTypeGoal.Type, + state: ChangeRecordTypeGoalsState.GoalState, ): ChangeRecordTypeGoalsViewData.GoalViewData { + val goal = state.type val goalViewData = when (goal) { is RecordTypeGoal.Type.Duration -> ChangeRecordTypeGoalsViewData.Type.Duration is RecordTypeGoal.Type.Count -> ChangeRecordTypeGoalsViewData.Type.Count @@ -113,12 +119,30 @@ class GoalsViewDataMapper @Inject constructor( } } }.map(CustomSpinner::CustomSpinnerTextItem) + val subtypeItems = listOf( + RecordTypeGoal.Subtype.Goal, + RecordTypeGoal.Subtype.Limit, + ).takeIf { + goal.value > 0L + }.orEmpty().map { + val name = when (it) { + is RecordTypeGoal.Subtype.Goal -> R.string.change_record_type_goal_time_hint + is RecordTypeGoal.Subtype.Limit -> R.string.change_record_type_limit_time_hint + }.let(resourceRepo::getString) + ChangeRecordTypeGoalSubtypeViewData( + subtype = it, + name = name, + isSelected = it::class.java == state.subtype::class.java, + textSizeSp = null, + ) + } return ChangeRecordTypeGoalsViewData.GoalViewData( title = title, typeItems = items, typeSelectedPosition = position, type = goalViewData, + subtypeItems = subtypeItems, value = value, ) } diff --git a/features/feature_change_goals/src/main/java/com/example/util/simpletimetracker/feature_change_goals/viewData/ChangeRecordTypeGoalSubtypeViewData.kt b/features/feature_change_goals/src/main/java/com/example/util/simpletimetracker/feature_change_goals/viewData/ChangeRecordTypeGoalSubtypeViewData.kt new file mode 100644 index 000000000..a89cf2030 --- /dev/null +++ b/features/feature_change_goals/src/main/java/com/example/util/simpletimetracker/feature_change_goals/viewData/ChangeRecordTypeGoalSubtypeViewData.kt @@ -0,0 +1,16 @@ +package com.example.util.simpletimetracker.feature_change_goals.viewData + +import com.example.util.simpletimetracker.core.view.buttonsRowView.ButtonsRowViewData +import com.example.util.simpletimetracker.domain.model.ChartFilterType +import com.example.util.simpletimetracker.domain.model.RecordTypeGoal +import com.example.util.simpletimetracker.feature_base_adapter.ViewHolderType + +data class ChangeRecordTypeGoalSubtypeViewData( + val subtype: RecordTypeGoal.Subtype, + override val name: String, + override val isSelected: Boolean, + override val textSizeSp: Int?, +) : ButtonsRowViewData() { + + override val id: Long = subtype::class.java.simpleName.hashCode().toLong() +} \ No newline at end of file diff --git a/features/feature_change_goals/src/main/java/com/example/util/simpletimetracker/feature_change_goals/viewData/ChangeRecordTypeGoalsState.kt b/features/feature_change_goals/src/main/java/com/example/util/simpletimetracker/feature_change_goals/viewData/ChangeRecordTypeGoalsState.kt index 1eaadb6c9..8c79814c0 100644 --- a/features/feature_change_goals/src/main/java/com/example/util/simpletimetracker/feature_change_goals/viewData/ChangeRecordTypeGoalsState.kt +++ b/features/feature_change_goals/src/main/java/com/example/util/simpletimetracker/feature_change_goals/viewData/ChangeRecordTypeGoalsState.kt @@ -4,9 +4,15 @@ import com.example.util.simpletimetracker.domain.model.DayOfWeek import com.example.util.simpletimetracker.domain.model.RecordTypeGoal data class ChangeRecordTypeGoalsState( - val session: RecordTypeGoal.Type, - val daily: RecordTypeGoal.Type, - val weekly: RecordTypeGoal.Type, - val monthly: RecordTypeGoal.Type, + val session: GoalState, + val daily: GoalState, + val weekly: GoalState, + val monthly: GoalState, val daysOfWeek: List, -) \ No newline at end of file +) { + + data class GoalState( + val type: RecordTypeGoal.Type, + val subtype: RecordTypeGoal.Subtype, + ) +} \ No newline at end of file diff --git a/features/feature_change_goals/views/src/main/java/com/example/util/simpletimetracker/feature_change_goals/views/GoalsViewDelegate.kt b/features/feature_change_goals/views/src/main/java/com/example/util/simpletimetracker/feature_change_goals/views/GoalsViewDelegate.kt index 8cb991020..0ff707de1 100644 --- a/features/feature_change_goals/views/src/main/java/com/example/util/simpletimetracker/feature_change_goals/views/GoalsViewDelegate.kt +++ b/features/feature_change_goals/views/src/main/java/com/example/util/simpletimetracker/feature_change_goals/views/GoalsViewDelegate.kt @@ -69,6 +69,9 @@ object GoalsViewDelegate { view.fieldChangeRecordTypeGoalDuration.setOnClick { viewModel.onGoalTimeClick(range) } + view.btnChangeRecordTypeGoalSubtype.listener = { + viewModel.onGoalSubTypeSelected(range, it) + } } initUx(RecordTypeGoal.Range.Session, layoutChangeRecordTypeGoalSession) @@ -155,6 +158,13 @@ object GoalsViewDelegate { view.inputChangeRecordTypeGoalCount.isVisible = true } } + + if (goal.subtypeItems.isNotEmpty()) { + view.btnChangeRecordTypeGoalSubtype.visible = true + view.btnChangeRecordTypeGoalSubtype.adapter.replace(goal.subtypeItems) + } else { + view.btnChangeRecordTypeGoalSubtype.visible = false + } } applyGoalToView(state.session, layoutChangeRecordTypeGoalSession) diff --git a/features/feature_change_goals/views/src/main/res/layout/change_goal_layout.xml b/features/feature_change_goals/views/src/main/res/layout/change_goal_layout.xml index d72f526f9..e65563c6f 100644 --- a/features/feature_change_goals/views/src/main/res/layout/change_goal_layout.xml +++ b/features/feature_change_goals/views/src/main/res/layout/change_goal_layout.xml @@ -158,11 +158,16 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginHorizontal="@dimen/edit_screen_field_margin_horizontal" - android:layout_marginBottom="2dp" android:overScrollMode="never" - app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toBottomOf="@id/containerChangeRecordTypeGoal" tools:itemCount="1" tools:listitem="@layout/item_day_of_week" /> + + \ No newline at end of file diff --git a/resources/src/main/res/values-ar/strings.xml b/resources/src/main/res/values-ar/strings.xml index 4f2d77fcf..25ece9ffc 100644 --- a/resources/src/main/res/values-ar/strings.xml +++ b/resources/src/main/res/values-ar/strings.xml @@ -159,6 +159,7 @@ لا توجد تصنيفات مضافة غير مفعل الهدف + حد إضافي المدة الافتراضية يتم تعقب الأنشطة ذات المدة الافتراضية فور النقر عليها. diff --git a/resources/src/main/res/values-ca/strings.xml b/resources/src/main/res/values-ca/strings.xml index 6a2bd7674..750c65581 100644 --- a/resources/src/main/res/values-ca/strings.xml +++ b/resources/src/main/res/values-ca/strings.xml @@ -159,6 +159,7 @@ No s\'han afegit categories Desactivat Objectiu + Límit Addicional Durada per defecte Les activitats amb una durada predeterminada es fan un seguiment immediatament en fer clic. diff --git a/resources/src/main/res/values-de/strings.xml b/resources/src/main/res/values-de/strings.xml index fd1e85464..7b71f6933 100644 --- a/resources/src/main/res/values-de/strings.xml +++ b/resources/src/main/res/values-de/strings.xml @@ -159,6 +159,7 @@ Keine Kategorien hinzugefügt Deaktiviert Ziel + Limit Zusätzlich Standarddauer Aktivitäten mit Standarddauer werden sofort beim Klicken verfolgt. diff --git a/resources/src/main/res/values-es/strings.xml b/resources/src/main/res/values-es/strings.xml index 78546ec84..b027bd038 100644 --- a/resources/src/main/res/values-es/strings.xml +++ b/resources/src/main/res/values-es/strings.xml @@ -159,6 +159,7 @@ No se añadieron categorías Deshabilitado Objetivo + Límite Adicional Duración predeterminada Las actividades con duración predeterminada se rastrean inmediatamente al hacer clic. diff --git a/resources/src/main/res/values-fa/strings.xml b/resources/src/main/res/values-fa/strings.xml index 2296aac7e..4686e4e36 100644 --- a/resources/src/main/res/values-fa/strings.xml +++ b/resources/src/main/res/values-fa/strings.xml @@ -159,6 +159,7 @@ دسته بندی ای اضافه نشد غیر فعال هدف + محدود کنید اضافی مدت زمان پیش فرض فعالیت‌های با مدت زمان پیش‌فرض بلافاصله با کلیک کردن ردیابی می‌شوند. diff --git a/resources/src/main/res/values-fr/strings.xml b/resources/src/main/res/values-fr/strings.xml index 824653ad7..3719841ef 100644 --- a/resources/src/main/res/values-fr/strings.xml +++ b/resources/src/main/res/values-fr/strings.xml @@ -159,6 +159,7 @@ Aucune catégorie ajoutée Désactivé Objectif + Limite Supplémentaire Durée par défaut Les activités avec une durée par défaut sont suivies immédiatement au clic. diff --git a/resources/src/main/res/values-hi/strings.xml b/resources/src/main/res/values-hi/strings.xml index 9ae296db0..0f392f1a0 100644 --- a/resources/src/main/res/values-hi/strings.xml +++ b/resources/src/main/res/values-hi/strings.xml @@ -159,6 +159,7 @@ कोई श्रेणियां नहीं जोड़ी अक्षम लक्ष्य + सीमा अतिरिक्त डिफ़ॉल्ट अवधि डिफ़ॉल्ट अवधि वाली गतिविधियों को क्लिक पर तुरंत ट्रैक किया जाता है। diff --git a/resources/src/main/res/values-in/strings.xml b/resources/src/main/res/values-in/strings.xml index 4ed6a6383..c8cdedcc8 100644 --- a/resources/src/main/res/values-in/strings.xml +++ b/resources/src/main/res/values-in/strings.xml @@ -159,6 +159,7 @@ Tidak ada kategori yang ditambahkan Dinonaktifkan Tujuan + Membatasi Tambahan Durasi bawaan Aktivitas dengan durasi default dilacak langsung saat diklik. diff --git a/resources/src/main/res/values-it/strings.xml b/resources/src/main/res/values-it/strings.xml index 66c89522a..7a6e0d7d6 100644 --- a/resources/src/main/res/values-it/strings.xml +++ b/resources/src/main/res/values-it/strings.xml @@ -159,6 +159,7 @@ Nessuna categoria aggiunta Disabilitato Obiettivo + Limite Ulteriori Durata predefinita Le attività con durata predefinita vengono tracciate immediatamente al clic. diff --git a/resources/src/main/res/values-iw/strings.xml b/resources/src/main/res/values-iw/strings.xml index cb4802e46..e15994fcd 100644 --- a/resources/src/main/res/values-iw/strings.xml +++ b/resources/src/main/res/values-iw/strings.xml @@ -159,6 +159,7 @@ לא נוספו קטגוריות מושבת יעד + לְהַגבִּיל נוסף משך ברירת מחדל מעקב אחר פעילויות עם משך ברירת מחדל מתבצע מיד בלחיצה. diff --git a/resources/src/main/res/values-ja/strings.xml b/resources/src/main/res/values-ja/strings.xml index cc891e188..87ed51713 100644 --- a/resources/src/main/res/values-ja/strings.xml +++ b/resources/src/main/res/values-ja/strings.xml @@ -159,6 +159,7 @@ カテゴリが追加されていません 未設定 目標 + 限界 追加 デフォルトの期間 デフォルトの期間のアクティビティは、クリックするとすぐに追跡されます。 diff --git a/resources/src/main/res/values-ko/strings.xml b/resources/src/main/res/values-ko/strings.xml index adac05877..8880874af 100644 --- a/resources/src/main/res/values-ko/strings.xml +++ b/resources/src/main/res/values-ko/strings.xml @@ -159,6 +159,7 @@ 카테고리 추가되지 않음 비활성화됨 목표 + 한계 추가의 기본 기간 기본 기간이 있는 활동은 클릭 시 즉시 추적됩니다. diff --git a/resources/src/main/res/values-nl/strings.xml b/resources/src/main/res/values-nl/strings.xml index b9144483e..9689aa0dd 100644 --- a/resources/src/main/res/values-nl/strings.xml +++ b/resources/src/main/res/values-nl/strings.xml @@ -159,6 +159,7 @@ Geen categorieën toegevoegd Uitgeschakeld Doel + Beperken Aanvullend Standaardduur Activiteiten met een standaardduur worden onmiddellijk na klikken gevolgd. diff --git a/resources/src/main/res/values-pl/strings.xml b/resources/src/main/res/values-pl/strings.xml index 247114385..55b422881 100644 --- a/resources/src/main/res/values-pl/strings.xml +++ b/resources/src/main/res/values-pl/strings.xml @@ -159,6 +159,7 @@ Brak dodanej kategorii Wyłączony Cel + Limit Dodatkowy Domyślny czas trwania Aktywności o domyślnym czasie trwania są śledzone natychmiast po kliknięciu. diff --git a/resources/src/main/res/values-pt-rPT/strings.xml b/resources/src/main/res/values-pt-rPT/strings.xml index 7c356cc72..c51a594a7 100644 --- a/resources/src/main/res/values-pt-rPT/strings.xml +++ b/resources/src/main/res/values-pt-rPT/strings.xml @@ -159,6 +159,7 @@ Nenhuma categoria adicionada Desativado Meta + Limite Adicional Duração padrão Atividades com duração padrão são rastreadas imediatamente após o clique. diff --git a/resources/src/main/res/values-pt/strings.xml b/resources/src/main/res/values-pt/strings.xml index 2fc8397c0..00304eabe 100644 --- a/resources/src/main/res/values-pt/strings.xml +++ b/resources/src/main/res/values-pt/strings.xml @@ -159,6 +159,7 @@ Nenhuma categoria adicionada Desativado Meta + Limite Adicional Duração padrão Atividades com duração padrão são rastreadas imediatamente após o clique. diff --git a/resources/src/main/res/values-ro/strings.xml b/resources/src/main/res/values-ro/strings.xml index 256018e61..15af86c15 100644 --- a/resources/src/main/res/values-ro/strings.xml +++ b/resources/src/main/res/values-ro/strings.xml @@ -159,6 +159,7 @@ Nu au fost categorii adăugate Dezactivat Țel + Limită Adiţional Durată implicită Activitățile cu durată implicită sunt urmărite imediat la clic. diff --git a/resources/src/main/res/values-ru/strings.xml b/resources/src/main/res/values-ru/strings.xml index ce3cf5247..b3a3f11be 100644 --- a/resources/src/main/res/values-ru/strings.xml +++ b/resources/src/main/res/values-ru/strings.xml @@ -159,6 +159,7 @@ Категории не добавлены Выкл. Цель + Лимит Дополнительно Продолжительность по умолчанию Действия с продолжительностью по умолчанию отслеживаются сразу по клику. diff --git a/resources/src/main/res/values-sv/strings.xml b/resources/src/main/res/values-sv/strings.xml index 1c8dd628e..87f3f5956 100644 --- a/resources/src/main/res/values-sv/strings.xml +++ b/resources/src/main/res/values-sv/strings.xml @@ -159,6 +159,7 @@ Inga kategorier har lagts till Inaktiverad Mål + Begränsa Ytterligare Standardvaraktighet Aktiviteter med standardvaraktighet spåras direkt vid klick. diff --git a/resources/src/main/res/values-tr/strings.xml b/resources/src/main/res/values-tr/strings.xml index 5c8caa059..e04b7b8d2 100644 --- a/resources/src/main/res/values-tr/strings.xml +++ b/resources/src/main/res/values-tr/strings.xml @@ -159,6 +159,7 @@ Kategori eklenmedi Devre dışı Hedef + Sınır Ek olarak Varsayılan süre Varsayılan süreye sahip etkinlikler, tıklandığında hemen izlenir. diff --git a/resources/src/main/res/values-uk/strings.xml b/resources/src/main/res/values-uk/strings.xml index 3e000dd50..9ad4f798e 100644 --- a/resources/src/main/res/values-uk/strings.xml +++ b/resources/src/main/res/values-uk/strings.xml @@ -159,6 +159,7 @@ Категорії не додано Вимкнено Ціль + Ліміт Додатково Тривалість за замовчуванням Дії з тривалістю за замовчуванням відстежуються одразу після натискання. diff --git a/resources/src/main/res/values-vi/strings.xml b/resources/src/main/res/values-vi/strings.xml index 01b55e8cd..21ddb9ecb 100644 --- a/resources/src/main/res/values-vi/strings.xml +++ b/resources/src/main/res/values-vi/strings.xml @@ -159,6 +159,7 @@ Chưa thêm danh mục nào Đã tắt Mục tiêu + Giới hạn Thêm vào Thời lượng mặc định Các hoạt động có thời lượng mặc định được theo dõi ngay lập tức khi nhấp chuột. diff --git a/resources/src/main/res/values-zh-rTW/strings.xml b/resources/src/main/res/values-zh-rTW/strings.xml index d8b74ea53..d7b708a94 100644 --- a/resources/src/main/res/values-zh-rTW/strings.xml +++ b/resources/src/main/res/values-zh-rTW/strings.xml @@ -159,6 +159,7 @@ 沒有新增分類 關閉 目標 + 限制 額外的 預設持續時間 點擊後會立即追蹤具有預設持續時間的活動。 diff --git a/resources/src/main/res/values-zh/strings.xml b/resources/src/main/res/values-zh/strings.xml index 7e61b114c..d79060c9e 100644 --- a/resources/src/main/res/values-zh/strings.xml +++ b/resources/src/main/res/values-zh/strings.xml @@ -159,6 +159,7 @@ 未添加任何类别 不启用 目标 + 限制 额外的 默认持续时间 单击后会立即跟踪具有默认持续时间的活动。 diff --git a/resources/src/main/res/values/strings.xml b/resources/src/main/res/values/strings.xml index 0d62f7484..8045084dd 100644 --- a/resources/src/main/res/values/strings.xml +++ b/resources/src/main/res/values/strings.xml @@ -159,6 +159,7 @@ No categories added Disabled Goal + Limit Additional Default duration Activities with default duration are tracked immediately on click.