diff --git a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/repo/PrefsRepoImpl.kt b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/repo/PrefsRepoImpl.kt index 49c18d73d..b1480e2b3 100644 --- a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/repo/PrefsRepoImpl.kt +++ b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/repo/PrefsRepoImpl.kt @@ -128,6 +128,10 @@ class PrefsRepoImpl @Inject constructor( KEY_KEEP_STATISTICS_RANGE, false, ) + override var retroactiveTrackingMode: Boolean by prefs.delegate( + KEY_RETROACTIVE_TRACKING_MODE, false + ) + override var firstDayOfWeek: Int by prefs.delegate( KEY_FIRST_DAY_OF_WEEK, firstDayOfWeekDefault, ) @@ -548,6 +552,7 @@ class PrefsRepoImpl @Inject constructor( const val KEY_CSV_EXPORT_CUSTOM_FILENAME = "csvExportCustomFilename" const val KEY_ICS_EXPORT_CUSTOM_FILENAME = "icsExportCustomFilename" const val KEY_KEEP_STATISTICS_RANGE = "keepStatisticsRange" + const val KEY_RETROACTIVE_TRACKING_MODE = "retroactiveTrackingMode" const val KEY_FIRST_DAY_OF_WEEK = "firstDayOfWeek" const val KEY_START_OF_DAY_SHIFT = "startOfDayShift" const val KEY_SHOW_UNTRACKED_IN_RECORDS = "showUntrackedInRecords" diff --git a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/resolver/BackupPrefsRepo.kt b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/resolver/BackupPrefsRepo.kt index 46233716b..e29b088d0 100644 --- a/data_local/src/main/java/com/example/util/simpletimetracker/data_local/resolver/BackupPrefsRepo.kt +++ b/data_local/src/main/java/com/example/util/simpletimetracker/data_local/resolver/BackupPrefsRepo.kt @@ -45,6 +45,7 @@ import com.example.util.simpletimetracker.data_local.repo.PrefsRepoImpl.Companio import com.example.util.simpletimetracker.data_local.repo.PrefsRepoImpl.Companion.KEY_RECORD_TYPES_FILTERED_ON_CHART import com.example.util.simpletimetracker.data_local.repo.PrefsRepoImpl.Companion.KEY_RECORD_TYPES_FILTERED_ON_LIST import com.example.util.simpletimetracker.data_local.repo.PrefsRepoImpl.Companion.KEY_REPEAT_BUTTON_TYPE +import com.example.util.simpletimetracker.data_local.repo.PrefsRepoImpl.Companion.KEY_RETROACTIVE_TRACKING_MODE import com.example.util.simpletimetracker.data_local.repo.PrefsRepoImpl.Companion.KEY_REVERSE_ORDER_IN_CALENDAR import com.example.util.simpletimetracker.data_local.repo.PrefsRepoImpl.Companion.KEY_SHOW_ACTIVITY_FILTERS import com.example.util.simpletimetracker.data_local.repo.PrefsRepoImpl.Companion.KEY_SHOW_CALENDAR_BUTTON_ON_RECORDS_TAB @@ -155,6 +156,7 @@ class BackupPrefsRepo @Inject constructor( PrefsProcessor(KEY_CSV_EXPORT_CUSTOM_FILENAME, ::csvExportCustomFileName), PrefsProcessor(KEY_ICS_EXPORT_CUSTOM_FILENAME, ::icsExportCustomFileName), PrefsProcessor(KEY_KEEP_STATISTICS_RANGE, ::keepStatisticsRange), + PrefsProcessor(KEY_RETROACTIVE_TRACKING_MODE, ::retroactiveTrackingMode), PrefsProcessor(KEY_FIRST_DAY_OF_WEEK, ::firstDayOfWeek), PrefsProcessor(KEY_START_OF_DAY_SHIFT, ::startOfDayShift), PrefsProcessor(KEY_SHOW_UNTRACKED_IN_RECORDS, ::showUntrackedInRecords), diff --git a/domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/AddRunningRecordMediator.kt b/domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/AddRunningRecordMediator.kt index 1fa60cfbf..b8a2df341 100644 --- a/domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/AddRunningRecordMediator.kt +++ b/domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/AddRunningRecordMediator.kt @@ -1,10 +1,12 @@ package com.example.util.simpletimetracker.domain.interactor +import com.example.util.simpletimetracker.domain.extension.orZero import com.example.util.simpletimetracker.domain.model.Range import com.example.util.simpletimetracker.domain.model.Record import com.example.util.simpletimetracker.domain.model.RecordType import com.example.util.simpletimetracker.domain.model.ResultContainer import com.example.util.simpletimetracker.domain.model.RunningRecord +import java.util.concurrent.TimeUnit import javax.inject.Inject class AddRunningRecordMediator @Inject constructor( @@ -79,15 +81,18 @@ class AddRunningRecordMediator @Inject constructor( tagIds = actualTags, comment = comment, ) - addInternal( - StartParams( - typeId = typeId, - comment = comment, - tagIds = actualTags, - timeStarted = timeStarted ?: System.currentTimeMillis(), - updateNotificationSwitch = updateNotificationSwitch, - ), + val startParams = StartParams( + typeId = typeId, + comment = comment, + tagIds = actualTags, + timeStarted = timeStarted ?: System.currentTimeMillis(), + updateNotificationSwitch = updateNotificationSwitch, ) + if (prefsInteractor.getRetroactiveTrackingMode()) { + addRetroactiveModeInternal(startParams) + } else { + addInternal(startParams) + } // Show goal count only on timer start, otherwise it would show on change also. notificationGoalCountInteractor.checkAndShow(typeId) pomodoroStartInteractor.checkAndStart(typeId) @@ -122,6 +127,25 @@ class AddRunningRecordMediator @Inject constructor( } } + private suspend fun addRetroactiveModeInternal(params: StartParams) { + val type = recordTypeInteractor.get(params.typeId) ?: return + val prevRecord = recordInteractor.getPrev(params.timeStarted).firstOrNull() + + if (type.defaultDuration > 0L) { + val newTimeStarted = prevRecord?.timeEnded + ?: (params.timeStarted - type.defaultDuration * 1000) + addInstantRecord( + params = params.copy(timeStarted = newTimeStarted), + type = type, + ) + } else { + addRecordRetroactively( + params = params, + prevRecord = prevRecord, + ) + } + } + private suspend fun addRunningRecord( params: StartParams, ) { @@ -165,6 +189,41 @@ class AddRunningRecordMediator @Inject constructor( } } + private suspend fun addRecordRetroactively( + params: StartParams, + prevRecord: Record?, + ) { + val shouldMergeWithPrevRecord = prevRecord != null && + prevRecord.typeId == params.typeId && + prevRecord.tagIds == params.tagIds + + val record = if (prevRecord != null && shouldMergeWithPrevRecord) { + Record( + id = prevRecord.id, // Updates existing record. + typeId = params.typeId, + timeStarted = prevRecord.timeStarted, + timeEnded = params.timeStarted, + comment = params.comment, + tagIds = params.tagIds, + ) + } else { + val newTimeStarted = prevRecord?.timeEnded + ?: (params.timeStarted - TimeUnit.MINUTES.toMillis(5)) + Record( + id = 0L, // Creates new record. + typeId = params.typeId, + timeStarted = newTimeStarted, + timeEnded = params.timeStarted, + comment = params.comment, + tagIds = params.tagIds, + ) + } + addRecordMediator.add( + record = record, + updateNotificationSwitch = params.updateNotificationSwitch, + ) + } + private suspend fun processRules( typeId: Long, timeStarted: Long, diff --git a/domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/PrefsInteractor.kt b/domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/PrefsInteractor.kt index 6f36ed48b..6f62bde61 100644 --- a/domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/PrefsInteractor.kt +++ b/domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/PrefsInteractor.kt @@ -205,6 +205,14 @@ class PrefsInteractor @Inject constructor( prefsRepo.keepStatisticsRange = isEnabled } + suspend fun getRetroactiveTrackingMode(): Boolean = withContext(Dispatchers.IO) { + prefsRepo.retroactiveTrackingMode + } + + suspend fun setRetroactiveTrackingMode(isEnabled: Boolean) = withContext(Dispatchers.IO) { + prefsRepo.retroactiveTrackingMode = isEnabled + } + suspend fun getFirstDayOfWeek(): DayOfWeek = withContext(Dispatchers.IO) { // Same as in java Calendar when (prefsRepo.firstDayOfWeek) { diff --git a/domain/src/main/java/com/example/util/simpletimetracker/domain/repo/PrefsRepo.kt b/domain/src/main/java/com/example/util/simpletimetracker/domain/repo/PrefsRepo.kt index 22d75096a..961a154c6 100644 --- a/domain/src/main/java/com/example/util/simpletimetracker/domain/repo/PrefsRepo.kt +++ b/domain/src/main/java/com/example/util/simpletimetracker/domain/repo/PrefsRepo.kt @@ -44,6 +44,8 @@ interface PrefsRepo { var keepStatisticsRange: Boolean + var retroactiveTrackingMode: Boolean + var firstDayOfWeek: Int var startOfDayShift: Long // in milliseconds diff --git a/features/feature_base_adapter/src/main/java/com/example/util/simpletimetracker/feature_base_adapter/record/RecordAdapterDelegate.kt b/features/feature_base_adapter/src/main/java/com/example/util/simpletimetracker/feature_base_adapter/record/RecordAdapterDelegate.kt index daed2f775..7c06e2c2b 100644 --- a/features/feature_base_adapter/src/main/java/com/example/util/simpletimetracker/feature_base_adapter/record/RecordAdapterDelegate.kt +++ b/features/feature_base_adapter/src/main/java/com/example/util/simpletimetracker/feature_base_adapter/record/RecordAdapterDelegate.kt @@ -9,7 +9,7 @@ import com.example.util.simpletimetracker.feature_base_adapter.databinding.ItemR import com.example.util.simpletimetracker.feature_base_adapter.record.RecordViewData as ViewData fun createRecordAdapterDelegate( - onItemClick: ((ViewData, Pair) -> Unit), + onItemClick: ((ViewData, Pair) -> Unit) = { _, _ -> }, onItemLongClick: ((ViewData, Pair) -> Unit) = { _, _ -> }, ) = createRecyclerBindingAdapterDelegate( Binding::inflate, diff --git a/features/feature_base_adapter/src/main/java/com/example/util/simpletimetracker/feature_base_adapter/recordWithHint/RecordWithHintAdapterDelegate.kt b/features/feature_base_adapter/src/main/java/com/example/util/simpletimetracker/feature_base_adapter/recordWithHint/RecordWithHintAdapterDelegate.kt new file mode 100644 index 000000000..19d3c6a2e --- /dev/null +++ b/features/feature_base_adapter/src/main/java/com/example/util/simpletimetracker/feature_base_adapter/recordWithHint/RecordWithHintAdapterDelegate.kt @@ -0,0 +1,25 @@ +package com.example.util.simpletimetracker.feature_base_adapter.recordWithHint + +import com.example.util.simpletimetracker.feature_base_adapter.createRecyclerBindingAdapterDelegate +import com.example.util.simpletimetracker.feature_base_adapter.databinding.ItemRecordWithHintLayoutBinding as Binding +import com.example.util.simpletimetracker.feature_base_adapter.recordWithHint.RecordWithHintViewData as ViewData + +fun createRecordWithHintAdapterDelegate() = createRecyclerBindingAdapterDelegate( + Binding::inflate, +) { binding, item, _ -> + + with(binding.viewRecordItem) { + item as ViewData + + item.record.let { item -> + itemColor = item.color + itemIcon = item.iconId + itemName = item.name + itemTagName = item.tagName + itemTimeStarted = item.timeStarted + itemTimeEnded = item.timeFinished + itemDuration = item.duration + itemComment = item.comment + } + } +} \ No newline at end of file diff --git a/features/feature_base_adapter/src/main/java/com/example/util/simpletimetracker/feature_base_adapter/recordWithHint/RecordWithHintViewData.kt b/features/feature_base_adapter/src/main/java/com/example/util/simpletimetracker/feature_base_adapter/recordWithHint/RecordWithHintViewData.kt new file mode 100644 index 000000000..f769be782 --- /dev/null +++ b/features/feature_base_adapter/src/main/java/com/example/util/simpletimetracker/feature_base_adapter/recordWithHint/RecordWithHintViewData.kt @@ -0,0 +1,14 @@ +package com.example.util.simpletimetracker.feature_base_adapter.recordWithHint + +import com.example.util.simpletimetracker.feature_base_adapter.ViewHolderType +import com.example.util.simpletimetracker.feature_base_adapter.record.RecordViewData + +data class RecordWithHintViewData( + val record: RecordViewData.Tracked, +) : ViewHolderType { + + override fun getUniqueId(): Long = record.id + + override fun isValidType(other: ViewHolderType): Boolean = + other is RecordWithHintViewData +} \ No newline at end of file diff --git a/features/feature_base_adapter/src/main/java/com/example/util/simpletimetracker/feature_base_adapter/runningRecord/RunningRecordAdapterDelegate.kt b/features/feature_base_adapter/src/main/java/com/example/util/simpletimetracker/feature_base_adapter/runningRecord/RunningRecordAdapterDelegate.kt index 822ac88bd..31e63f174 100644 --- a/features/feature_base_adapter/src/main/java/com/example/util/simpletimetracker/feature_base_adapter/runningRecord/RunningRecordAdapterDelegate.kt +++ b/features/feature_base_adapter/src/main/java/com/example/util/simpletimetracker/feature_base_adapter/runningRecord/RunningRecordAdapterDelegate.kt @@ -10,7 +10,7 @@ import com.example.util.simpletimetracker.feature_base_adapter.runningRecord.Run fun createRunningRecordAdapterDelegate( transitionNamePrefix: String, - onItemClick: ((ViewData, Pair) -> Unit), + onItemClick: ((ViewData, Pair) -> Unit) = { _, _ -> }, onItemLongClick: ((ViewData, Pair) -> Unit) = { _, _ -> }, ) = createRecyclerBindingAdapterDelegate( Binding::inflate, diff --git a/features/feature_base_adapter/src/main/res/layout/item_record_with_hint_layout.xml b/features/feature_base_adapter/src/main/res/layout/item_record_with_hint_layout.xml new file mode 100644 index 000000000..808bd64a9 --- /dev/null +++ b/features/feature_base_adapter/src/main/res/layout/item_record_with_hint_layout.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/view/RecordsFilterFragment.kt b/features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/view/RecordsFilterFragment.kt index 8aadbf302..5c1f35baa 100644 --- a/features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/view/RecordsFilterFragment.kt +++ b/features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/view/RecordsFilterFragment.kt @@ -77,7 +77,7 @@ class RecordsFilterFragment : createRecordsDateDividerAdapterDelegate(), createRecordTypeAdapterDelegate(viewModel::onRecordTypeClick), createCategoryAdapterDelegate(viewModel::onCategoryClick), - createRecordAdapterDelegate(viewModel::onRecordClick), + createRecordAdapterDelegate(onItemClick = viewModel::onRecordClick), createSelectionButtonAdapterDelegate(viewModel::onSelectionButtonClick), createRecordsFilterCommentAdapterDelegate(viewModel::onCommentChange), createRecordsFilterButtonAdapterDelegate(viewModel::onInnerFilterButtonClick), @@ -94,7 +94,7 @@ class RecordsFilterFragment : createLoaderAdapterDelegate(), createEmptyAdapterDelegate(), createRecordsDateDividerAdapterDelegate(), - createRunningRecordAdapterDelegate("", { _, _ -> }), + createRunningRecordAdapterDelegate(""), createRecordAdapterDelegate(viewModel::onRecordClick), createMultitaskRecordAdapterDelegate(), ) diff --git a/features/feature_running_records/src/main/java/com/example/util/simpletimetracker/feature_running_records/interactor/RunningRecordsViewDataInteractor.kt b/features/feature_running_records/src/main/java/com/example/util/simpletimetracker/feature_running_records/interactor/RunningRecordsViewDataInteractor.kt index e5c642022..533c5d4c4 100644 --- a/features/feature_running_records/src/main/java/com/example/util/simpletimetracker/feature_running_records/interactor/RunningRecordsViewDataInteractor.kt +++ b/features/feature_running_records/src/main/java/com/example/util/simpletimetracker/feature_running_records/interactor/RunningRecordsViewDataInteractor.kt @@ -6,6 +6,7 @@ import com.example.util.simpletimetracker.core.interactor.GetCurrentRecordsDurat import com.example.util.simpletimetracker.core.interactor.GetRunningRecordViewDataMediator import com.example.util.simpletimetracker.core.mapper.RecordTypeViewDataMapper import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor +import com.example.util.simpletimetracker.domain.interactor.RecordInteractor import com.example.util.simpletimetracker.domain.interactor.RecordTagInteractor import com.example.util.simpletimetracker.domain.interactor.RecordTypeGoalInteractor import com.example.util.simpletimetracker.domain.interactor.RecordTypeInteractor @@ -23,6 +24,7 @@ class RunningRecordsViewDataInteractor @Inject constructor( private val recordTagInteractor: RecordTagInteractor, private val recordTypeGoalInteractor: RecordTypeGoalInteractor, private val runningRecordInteractor: RunningRecordInteractor, + private val recordInteractor: RecordInteractor, private val activityFilterViewDataInteractor: ActivityFilterViewDataInteractor, private val mapper: RunningRecordsViewDataMapper, private val recordTypeViewDataMapper: RecordTypeViewDataMapper, @@ -31,6 +33,8 @@ class RunningRecordsViewDataInteractor @Inject constructor( private val filterGoalsByDayOfWeekInteractor: FilterGoalsByDayOfWeekInteractor, ) { + // TODO RETRO what to do on first start, when there is no prev record? + // TODO RETRO show timers also if any suspend fun getViewData( completeTypeIds: Set, ): List { @@ -49,6 +53,7 @@ class RunningRecordsViewDataInteractor @Inject constructor( val showPomodoroButton = prefsInteractor.getEnablePomodoroMode() val showRepeatButton = prefsInteractor.getEnableRepeatButton() val isPomodoroStarted = prefsInteractor.getPomodoroModeStartedTimestampMs() != 0L + val retroactiveTrackingModeEnabled = prefsInteractor.getRetroactiveTrackingMode() val goals = filterGoalsByDayOfWeekInteractor .execute(recordTypeGoalInteractor.getAllTypeGoals()) .groupBy { it.idData.value } @@ -63,10 +68,26 @@ class RunningRecordsViewDataInteractor @Inject constructor( } val runningRecordsViewData = when { - showFirstEnterHint -> + showFirstEnterHint -> { listOf(mapper.mapToTypesEmpty()) - runningRecords.isEmpty() -> + } + retroactiveTrackingModeEnabled -> { + val prevRecord = recordInteractor.getPrev( + timeStarted = System.currentTimeMillis(), + ).firstOrNull() + mapper.mapToRetroActiveMode( + typesMap = recordTypesMap, + recordTags = recordTags, + prevRecord = prevRecord, + isDarkTheme = isDarkTheme, + useProportionalMinutes = useProportionalMinutes, + useMilitaryTime = useMilitaryTime, + showSeconds = showSeconds, + ) + } + runningRecords.isEmpty() -> { listOf(mapper.mapToEmpty()) + } else -> { runningRecords .sortedByDescending(RunningRecord::timeStarted) diff --git a/features/feature_running_records/src/main/java/com/example/util/simpletimetracker/feature_running_records/mapper/RunningRecordsViewDataMapper.kt b/features/feature_running_records/src/main/java/com/example/util/simpletimetracker/feature_running_records/mapper/RunningRecordsViewDataMapper.kt index df3527a52..854b012a7 100644 --- a/features/feature_running_records/src/main/java/com/example/util/simpletimetracker/feature_running_records/mapper/RunningRecordsViewDataMapper.kt +++ b/features/feature_running_records/src/main/java/com/example/util/simpletimetracker/feature_running_records/mapper/RunningRecordsViewDataMapper.kt @@ -1,15 +1,28 @@ package com.example.util.simpletimetracker.feature_running_records.mapper +import com.example.util.simpletimetracker.core.mapper.ColorMapper +import com.example.util.simpletimetracker.core.mapper.RecordViewDataMapper +import com.example.util.simpletimetracker.core.mapper.RunningRecordViewDataMapper import com.example.util.simpletimetracker.core.repo.ResourceRepo +import com.example.util.simpletimetracker.domain.UNTRACKED_ITEM_ID +import com.example.util.simpletimetracker.domain.model.AppColor +import com.example.util.simpletimetracker.domain.model.Record +import com.example.util.simpletimetracker.domain.model.RecordTag +import com.example.util.simpletimetracker.domain.model.RecordType +import com.example.util.simpletimetracker.domain.model.RunningRecord 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.hint.HintViewData import com.example.util.simpletimetracker.feature_base_adapter.hintBig.HintBigViewData +import com.example.util.simpletimetracker.feature_base_adapter.recordWithHint.RecordWithHintViewData import com.example.util.simpletimetracker.feature_running_records.R import javax.inject.Inject class RunningRecordsViewDataMapper @Inject constructor( private val resourceRepo: ResourceRepo, + private val colorMapper: ColorMapper, + private val runningRecordViewDataMapper: RunningRecordViewDataMapper, + private val recordViewDataMapper: RecordViewDataMapper, ) { fun mapToTypesEmpty(): ViewHolderType { @@ -38,4 +51,78 @@ class RunningRecordsViewDataMapper @Inject constructor( paddingBottom = 0, ) } + + // TODO RETRO move strings to res. + // TODO RETRO check repeat. + // TODO RETRO check instant activities. + // TODO RETRO check record actions. + // TODO RETRO add scroll to top on first click when there were no records, otherwise hint is not visible. + // TODO RETRO check pomodoro start on activity click. + fun mapToRetroActiveMode( + typesMap: Map, + recordTags: List, + prevRecord: Record?, + isDarkTheme: Boolean, + useProportionalMinutes: Boolean, + useMilitaryTime: Boolean, + showSeconds: Boolean, + ): List { + val result = mutableListOf() + + if (prevRecord == null) { + result += EmptyViewData( + message = "Click on card to select what you have been doing", + hint = R.string.running_records_empty_hint.let(resourceRepo::getString), + ) + } + + val type = prevRecord?.typeId?.let(typesMap::get) + if (prevRecord != null && type != null) { + result += runningRecordViewDataMapper.map( + runningRecord = RunningRecord( + id = UNTRACKED_ITEM_ID, + timeStarted = prevRecord.timeEnded, + comment = "", + ), + dailyCurrent = null, + recordType = RecordType( + id = 0L, + name = resourceRepo.getString(R.string.untracked_time_name), + icon = "", + color = AppColor( + 0, colorMapper.toUntrackedColor(isDarkTheme).toString(), + ), + defaultDuration = 0, + note = "", + ), + recordTags = emptyList(), + goals = emptyList(), + isDarkTheme = isDarkTheme, + useMilitaryTime = useMilitaryTime, + showSeconds = showSeconds, + useProportionalMinutes = useProportionalMinutes, + nowIconVisible = false, + goalsVisible = false, + totalDurationVisible = false, + ) + result += recordViewDataMapper.map( + record = prevRecord, + recordType = type, + recordTags = recordTags.filter { it.id in prevRecord.tagIds }, + isDarkTheme = isDarkTheme, + useMilitaryTime = useMilitaryTime, + useProportionalMinutes = useProportionalMinutes, + showSeconds = showSeconds, + ).let { + RecordWithHintViewData(it) + } + result += HintViewData( + text = "Select what you have been doing", + paddingTop = 0, + paddingBottom = 0, + ) + } + + return result + } } \ No newline at end of file diff --git a/features/feature_running_records/src/main/java/com/example/util/simpletimetracker/feature_running_records/view/RunningRecordsFragment.kt b/features/feature_running_records/src/main/java/com/example/util/simpletimetracker/feature_running_records/view/RunningRecordsFragment.kt index f138f1942..dde596d24 100644 --- a/features/feature_running_records/src/main/java/com/example/util/simpletimetracker/feature_running_records/view/RunningRecordsFragment.kt +++ b/features/feature_running_records/src/main/java/com/example/util/simpletimetracker/feature_running_records/view/RunningRecordsFragment.kt @@ -21,6 +21,7 @@ import com.example.util.simpletimetracker.feature_base_adapter.hintBig.createHin import com.example.util.simpletimetracker.feature_base_adapter.loader.createLoaderAdapterDelegate import com.example.util.simpletimetracker.feature_base_adapter.recordType.createRecordTypeAdapterDelegate import com.example.util.simpletimetracker.feature_base_adapter.recordTypeSpecial.createRunningRecordTypeSpecialAdapterDelegate +import com.example.util.simpletimetracker.feature_base_adapter.recordWithHint.createRecordWithHintAdapterDelegate import com.example.util.simpletimetracker.feature_base_adapter.runningRecord.createRunningRecordAdapterDelegate import com.example.util.simpletimetracker.feature_running_records.viewModel.RunningRecordsViewModel import com.example.util.simpletimetracker.feature_views.TransitionNames @@ -68,6 +69,7 @@ class RunningRecordsFragment : onItemLongClick = viewModel::onRecordTypeLongClick, withTransition = true, ), + createRecordWithHintAdapterDelegate(), createRunningRecordTypeSpecialAdapterDelegate(throttle(viewModel::onSpecialRecordTypeClick)), createActivityFilterAdapterDelegate(viewModel::onActivityFilterClick, viewModel::onActivityFilterLongClick), createActivityFilterAddAdapterDelegate(throttle(viewModel::onAddActivityFilterClick)), diff --git a/features/feature_running_records/src/main/res/layout/running_records_fragment.xml b/features/feature_running_records/src/main/res/layout/running_records_fragment.xml index 2bf100c5d..5cb7ef697 100644 --- a/features/feature_running_records/src/main/res/layout/running_records_fragment.xml +++ b/features/feature_running_records/src/main/res/layout/running_records_fragment.xml @@ -4,6 +4,7 @@ android:id="@+id/rvRunningRecordsList" android:layout_width="match_parent" android:layout_height="match_parent" + android:clipChildren="false" android:clipToPadding="false" tools:itemCount="3" tools:listitem="@layout/item_running_record_layout" /> diff --git a/features/feature_settings/api/src/main/java/com/example/util/simpletimetracker/feature_settings/api/SettingsBlock.kt b/features/feature_settings/api/src/main/java/com/example/util/simpletimetracker/feature_settings/api/SettingsBlock.kt index 0eeb6ef5c..09d19981b 100644 --- a/features/feature_settings/api/src/main/java/com/example/util/simpletimetracker/feature_settings/api/SettingsBlock.kt +++ b/features/feature_settings/api/src/main/java/com/example/util/simpletimetracker/feature_settings/api/SettingsBlock.kt @@ -73,6 +73,7 @@ enum class SettingsBlock { AdditionalTagSelectionExcludeActivities, AdditionalCloseAfterOneTag, AdditionalKeepStatisticsRange, + AdditionalRetroactiveTrackingMode, AdditionalKeepScreenOn, AdditionalFirstDayOfWeek, AdditionalShiftStartOfDay, diff --git a/features/feature_settings/src/main/java/com/example/util/simpletimetracker/feature_settings/interactor/SettingsAdditionalViewDataInteractor.kt b/features/feature_settings/src/main/java/com/example/util/simpletimetracker/feature_settings/interactor/SettingsAdditionalViewDataInteractor.kt index aef371b7d..da6c1df1a 100644 --- a/features/feature_settings/src/main/java/com/example/util/simpletimetracker/feature_settings/interactor/SettingsAdditionalViewDataInteractor.kt +++ b/features/feature_settings/src/main/java/com/example/util/simpletimetracker/feature_settings/interactor/SettingsAdditionalViewDataInteractor.kt @@ -94,6 +94,15 @@ class SettingsAdditionalViewDataInteractor @Inject constructor( dividerIsVisible = true, ) + result += SettingsCheckboxViewData( + block = SettingsBlock.AdditionalRetroactiveTrackingMode, + title = resourceRepo.getString(R.string.settings_retroactive_tracking_mode), + subtitle = resourceRepo.getString(R.string.settings_retroactive_tracking_mode_hint), + isChecked = prefsInteractor.getRetroactiveTrackingMode(), + bottomSpaceIsVisible = true, + dividerIsVisible = true, + ) + result += SettingsCheckboxViewData( block = SettingsBlock.AdditionalKeepScreenOn, title = resourceRepo.getString(R.string.settings_keep_screen_on), diff --git a/features/feature_settings/src/main/java/com/example/util/simpletimetracker/feature_settings/viewModel/delegate/SettingsAdditionalViewModelDelegate.kt b/features/feature_settings/src/main/java/com/example/util/simpletimetracker/feature_settings/viewModel/delegate/SettingsAdditionalViewModelDelegate.kt index b65ecaec3..6a70a2348 100644 --- a/features/feature_settings/src/main/java/com/example/util/simpletimetracker/feature_settings/viewModel/delegate/SettingsAdditionalViewModelDelegate.kt +++ b/features/feature_settings/src/main/java/com/example/util/simpletimetracker/feature_settings/viewModel/delegate/SettingsAdditionalViewModelDelegate.kt @@ -11,6 +11,8 @@ import com.example.util.simpletimetracker.domain.interactor.NotificationActivity import com.example.util.simpletimetracker.domain.interactor.NotificationGoalTimeInteractor import com.example.util.simpletimetracker.domain.interactor.NotificationTypeInteractor import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor +import com.example.util.simpletimetracker.domain.interactor.RemoveRunningRecordMediator +import com.example.util.simpletimetracker.domain.interactor.RunningRecordInteractor import com.example.util.simpletimetracker.domain.interactor.WidgetInteractor import com.example.util.simpletimetracker.domain.model.WidgetType import com.example.util.simpletimetracker.feature_base_adapter.ViewHolderType @@ -36,6 +38,8 @@ class SettingsAdditionalViewModelDelegate @Inject constructor( private val widgetInteractor: WidgetInteractor, private val notificationGoalTimeInteractor: NotificationGoalTimeInteractor, private val settingsAdditionalViewDataInteractor: SettingsAdditionalViewDataInteractor, + private val runningRecordInteractor: RunningRecordInteractor, + private val removeRunningRecordMediator: RemoveRunningRecordMediator, ) : ViewModelDelegate() { val keepScreenOnCheckbox: LiveData @@ -65,6 +69,7 @@ class SettingsAdditionalViewModelDelegate @Inject constructor( SettingsBlock.AdditionalCloseAfterOneTag -> onRecordTagSelectionCloseClicked() SettingsBlock.AdditionalTagSelectionExcludeActivities -> onRecordTagSelectionExcludeActivitiesClicked() SettingsBlock.AdditionalKeepStatisticsRange -> onKeepStatisticsRangeClicked() + SettingsBlock.AdditionalRetroactiveTrackingMode -> onRetroactiveTrackingModeClicked() SettingsBlock.AdditionalSendEvents -> onAutomatedTrackingSendEventsClicked() SettingsBlock.AdditionalKeepScreenOn -> onKeepScreenOnClicked() SettingsBlock.AdditionalDataEdit -> onDataEditClick() @@ -157,6 +162,20 @@ class SettingsAdditionalViewModelDelegate @Inject constructor( } } + private fun onRetroactiveTrackingModeClicked() { + delegateScope.launch { + val newValue = !prefsInteractor.getRetroactiveTrackingMode() + prefsInteractor.setRetroactiveTrackingMode(newValue) + parent?.updateContent() + runningRecordInteractor.getAll().forEach { + removeRunningRecordMediator.removeWithRecordAdd(it) + } + // TODO RETRO update widgets + // TODO RETRO update notifs + // TODO RETRO update wear + } + } + private fun onIgnoreShortRecordsClicked() { delegateScope.launch { DurationDialogParams( diff --git a/resources/src/main/res/values/strings.xml b/resources/src/main/res/values/strings.xml index b5f30b5cd..fc5af821d 100644 --- a/resources/src/main/res/values/strings.xml +++ b/resources/src/main/res/values/strings.xml @@ -297,6 +297,8 @@ Hide when timer notification is shown Keep statistics range If enabled detailed statistics will be opened with the same time range selected in statistics. + Enable retroactive time tracking + Track time by selecting which activity have been done since last time rather than which activity will be done from now. Shift start of the day Start of day will be shifted by the specified amount of time, forward or backward depending on the sign. Today starts at %s