diff --git a/app/src/main/java/com/example/util/simpletimetracker/di/NavigationScreenMapModule.kt b/app/src/main/java/com/example/util/simpletimetracker/di/NavigationScreenMapModule.kt index a7ecfaad..a0f14bc0 100644 --- a/app/src/main/java/com/example/util/simpletimetracker/di/NavigationScreenMapModule.kt +++ b/app/src/main/java/com/example/util/simpletimetracker/di/NavigationScreenMapModule.kt @@ -23,7 +23,8 @@ import com.example.util.simpletimetracker.navigation.params.screen.ChangeRecordT import com.example.util.simpletimetracker.navigation.params.screen.ChangeRecordTagFromChangeRunningRecordParams import com.example.util.simpletimetracker.navigation.params.screen.ChangeRecordTagFromTagsParams import com.example.util.simpletimetracker.navigation.params.screen.ChangeRecordTypeParams -import com.example.util.simpletimetracker.navigation.params.screen.ChangeRunningRecordParams +import com.example.util.simpletimetracker.navigation.params.screen.ChangeRunningRecordFromMainParams +import com.example.util.simpletimetracker.navigation.params.screen.ChangeRunningRecordFromRecordsAllParams import com.example.util.simpletimetracker.navigation.params.screen.DataEditParams import com.example.util.simpletimetracker.navigation.params.screen.RecordsAllParams import com.example.util.simpletimetracker.navigation.params.screen.StatisticsDetailParams @@ -59,14 +60,24 @@ class NavigationScreenMapModule { @IntoMap @Provides - @ScreenKey(ChangeRunningRecordParams::class) - fun changeRecordRunning(): NavigationData { + @ScreenKey(ChangeRunningRecordFromMainParams::class) + fun changeRecordRunningFromMain(): NavigationData { return NavigationData( R.id.action_mainFragment_to_changeRunningRecordFragment, bundleCreatorDelegate(ChangeRunningRecordFragment::createBundle) ) } + @IntoMap + @Provides + @ScreenKey(ChangeRunningRecordFromRecordsAllParams::class) + fun changeRecordRunningFromRecordsAll(): NavigationData { + return NavigationData( + R.id.action_recordsAllFragment_to_changeRunningRecordFragment, + bundleCreatorDelegate(ChangeRunningRecordFragment::createBundle) + ) + } + @IntoMap @Provides @ScreenKey(ChangeRecordFromMainParams::class) diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 94d4427f..cf6f8b1c 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -99,6 +99,9 @@ + - Range( - timeStarted = start, - timeEnded = end - ) - } + ) } data class Result( diff --git a/core/src/main/java/com/example/util/simpletimetracker/core/interactor/GetUntrackedRecordsInteractorImpl.kt b/core/src/main/java/com/example/util/simpletimetracker/core/interactor/GetUntrackedRecordsInteractorImpl.kt index f2330027..ac773979 100644 --- a/core/src/main/java/com/example/util/simpletimetracker/core/interactor/GetUntrackedRecordsInteractorImpl.kt +++ b/core/src/main/java/com/example/util/simpletimetracker/core/interactor/GetUntrackedRecordsInteractorImpl.kt @@ -46,8 +46,8 @@ class GetUntrackedRecordsInteractorImpl @Inject constructor( ).map { Record( typeId = UNTRACKED_ITEM_ID, - timeStarted = it.first, - timeEnded = it.second, + timeStarted = it.timeStarted, + timeEnded = it.timeEnded, comment = "" ) }.let { diff --git a/core/src/main/java/com/example/util/simpletimetracker/core/interactor/RecordFilterInteractor.kt b/core/src/main/java/com/example/util/simpletimetracker/core/interactor/RecordFilterInteractor.kt index 2d7e06ce..270ecd0d 100644 --- a/core/src/main/java/com/example/util/simpletimetracker/core/interactor/RecordFilterInteractor.kt +++ b/core/src/main/java/com/example/util/simpletimetracker/core/interactor/RecordFilterInteractor.kt @@ -23,10 +23,13 @@ import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor import com.example.util.simpletimetracker.domain.interactor.RecordInteractor import com.example.util.simpletimetracker.domain.interactor.RecordTypeCategoryInteractor import com.example.util.simpletimetracker.domain.interactor.RecordTypeInteractor +import com.example.util.simpletimetracker.domain.interactor.RunningRecordInteractor +import com.example.util.simpletimetracker.domain.mapper.RangeMapper import com.example.util.simpletimetracker.domain.model.DayOfWeek 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.RecordBase import com.example.util.simpletimetracker.domain.model.RecordsFilter import java.util.Calendar import java.util.concurrent.TimeUnit @@ -38,8 +41,10 @@ class RecordFilterInteractor @Inject constructor( private val interactor: RecordInteractor, private val recordTypeInteractor: RecordTypeInteractor, private val recordTypeCategoryInteractor: RecordTypeCategoryInteractor, + private val runningRecordInteractor: RunningRecordInteractor, private val getUntrackedRecordsInteractor: GetUntrackedRecordsInteractor, private val timeMapper: TimeMapper, + private val rangeMapper: RangeMapper, private val prefsInteractor: PrefsInteractor, ) { @@ -57,16 +62,16 @@ class RecordFilterInteractor @Inject constructor( startOfDayShift = startOfDayShift ) - return@withContext if (range.first == 0L && range.second == 0L) { + return@withContext if (range.timeStarted == 0L && range.timeEnded == 0L) { null } else { - RecordsFilter.Date(Range(range.first, range.second)) + RecordsFilter.Date(range) } } suspend fun getByFilter( filters: List, - ): List = withContext(Dispatchers.Default) { + ): List = withContext(Dispatchers.Default) { if (filters.isEmpty()) return@withContext emptyList() val startOfDayShift = prefsInteractor.getStartOfDayShift() @@ -79,6 +84,7 @@ class RecordFilterInteractor @Inject constructor( } else -> filters.getTypeIds() } + val runningRecords = runningRecordInteractor.getAll() val selectedCommentItems: List = filters.getCommentItems() val comments: List = selectedCommentItems.getComments().map(String::lowercase) val selectedNoComment: Boolean = selectedCommentItems.hasNoComment() @@ -97,13 +103,14 @@ class RecordFilterInteractor @Inject constructor( // TODO Use different queries for optimization. // TODO by tag (tagged, untagged). - val records: List = when { + val records: List = when { filters.hasUntrackedFilter() -> { val range = ranges.firstOrNull() ?: Range(0, 0) val records = if (range.timeStarted == 0L && range.timeEnded == 0L) { - interactor.getAll() + interactor.getAll() + runningRecords } else { - interactor.getFromRange(range) + interactor.getFromRange(range) + + rangeMapper.getRunningRecordsFromRange(runningRecords, range) }.map { Range(it.timeStarted, it.timeEnded) } getUntrackedRecordsInteractor.get(range, records) } @@ -141,13 +148,15 @@ class RecordFilterInteractor @Inject constructor( interactor.searchAnyComments() } else -> interactor.getAll() + }.let { + if (filters.hasUntrackedFilter()) it else it + runningRecords } - fun Record.selectedByActivity(): Boolean { + fun RecordBase.selectedByActivity(): Boolean { return typeIds.isEmpty() || typeId in typeIds } - fun Record.selectedByComment(): Boolean { + fun RecordBase.selectedByComment(): Boolean { if (selectedCommentItems.isEmpty()) return true val comment = this.comment.lowercase() return (selectedNoComment && comment.isEmpty()) || @@ -155,12 +164,12 @@ class RecordFilterInteractor @Inject constructor( (comment.isNotEmpty() && comments.any { comment.contains(it) }) } - fun Record.selectedByDate(): Boolean { + fun RecordBase.selectedByDate(): Boolean { if (ranges.isEmpty()) return true return ranges.any { range -> timeStarted < range.timeEnded && timeEnded > range.timeStarted } } - fun Record.selectedByTag(): Boolean { + fun RecordBase.selectedByTag(): Boolean { if (selectedTagItems.isEmpty()) return true return if (tagIds.isNotEmpty()) { tagIds.any { tagId -> tagId in selectedTaggedIds } @@ -169,7 +178,7 @@ class RecordFilterInteractor @Inject constructor( } } - fun Record.filteredByTag(): Boolean { + fun RecordBase.filteredByTag(): Boolean { if (filteredTagItems.isEmpty()) return false return if (tagIds.isNotEmpty()) { tagIds.any { tagId -> tagId in filteredTaggedIds } @@ -178,12 +187,13 @@ class RecordFilterInteractor @Inject constructor( } } - fun Record.isManuallyFiltered(): Boolean { + fun RecordBase.isManuallyFiltered(): Boolean { if (manuallyFilteredIds.isEmpty()) return false + if (this !is Record) return false return id in manuallyFilteredIds } - fun Record.selectedByDayOfWeek(): Boolean { + fun RecordBase.selectedByDayOfWeek(): Boolean { if (daysOfWeek.isEmpty()) return true val daysOfRecord: MutableSet = mutableSetOf() @@ -224,7 +234,7 @@ class RecordFilterInteractor @Inject constructor( return daysOfRecord.any { it in daysOfWeek } } - fun Record.selectedByTimeOfDay(): Boolean { + fun RecordBase.selectedByTimeOfDay(): Boolean { if (timeOfDay == null) return true // Check empty range. @@ -250,7 +260,7 @@ class RecordFilterInteractor @Inject constructor( } } - fun Record.selectedByDuration(): Boolean { + fun RecordBase.selectedByDuration(): Boolean { if (durations.isEmpty()) return true return durations.any { duration >= it.timeStarted && duration <= it.timeEnded } } diff --git a/core/src/main/java/com/example/util/simpletimetracker/core/interactor/StatisticsMediator.kt b/core/src/main/java/com/example/util/simpletimetracker/core/interactor/StatisticsMediator.kt index 08bdf873..213de175 100644 --- a/core/src/main/java/com/example/util/simpletimetracker/core/interactor/StatisticsMediator.kt +++ b/core/src/main/java/com/example/util/simpletimetracker/core/interactor/StatisticsMediator.kt @@ -38,7 +38,7 @@ class StatisticsMediator @Inject constructor( val firstDayOfWeek = prefsInteractor.getFirstDayOfWeek() val startOfDayShift = prefsInteractor.getStartOfDayShift() - val (start, end) = timeMapper.getRangeStartAndEnd( + val range = timeMapper.getRangeStartAndEnd( rangeLength = rangeLength, shift = shift, firstDayOfWeek = firstDayOfWeek, @@ -47,7 +47,7 @@ class StatisticsMediator @Inject constructor( return getFromRange( filterType = filterType, - range = Range(start, end), + range = range, addUntracked = !filteredIds.contains(UNTRACKED_ITEM_ID), addUncategorized = !filteredIds.contains(UNCATEGORIZED_ITEM_ID), ) diff --git a/core/src/main/java/com/example/util/simpletimetracker/core/mapper/TimeMapper.kt b/core/src/main/java/com/example/util/simpletimetracker/core/mapper/TimeMapper.kt index dd11343c..bb3c846d 100644 --- a/core/src/main/java/com/example/util/simpletimetracker/core/mapper/TimeMapper.kt +++ b/core/src/main/java/com/example/util/simpletimetracker/core/mapper/TimeMapper.kt @@ -5,6 +5,7 @@ import com.example.util.simpletimetracker.core.extension.setWeekToFirstDay import com.example.util.simpletimetracker.core.provider.CurrentTimestampProvider import com.example.util.simpletimetracker.core.repo.ResourceRepo import com.example.util.simpletimetracker.domain.model.DayOfWeek +import com.example.util.simpletimetracker.domain.model.Range import com.example.util.simpletimetracker.domain.model.RangeLength import java.text.SimpleDateFormat import java.util.Calendar @@ -337,7 +338,7 @@ class TimeMapper @Inject constructor( shift: Int, firstDayOfWeek: DayOfWeek, startOfDayShift: Long, - ): Pair { + ): Range { val dayOfWeek = toCalendarDayOfWeek(firstDayOfWeek) val rangeStart: Long val rangeEnd: Long @@ -408,7 +409,7 @@ class TimeMapper @Inject constructor( } } - return rangeStart to rangeEnd + return Range(rangeStart, rangeEnd) } fun getActualMaximum( diff --git a/core/src/test/java/com/example/util/simpletimetracker/core/mapper/TimeMapperGetRangeStartAndEndTest.kt b/core/src/test/java/com/example/util/simpletimetracker/core/mapper/TimeMapperGetRangeStartAndEndTest.kt index 2f6f91e6..2ce4f956 100644 --- a/core/src/test/java/com/example/util/simpletimetracker/core/mapper/TimeMapperGetRangeStartAndEndTest.kt +++ b/core/src/test/java/com/example/util/simpletimetracker/core/mapper/TimeMapperGetRangeStartAndEndTest.kt @@ -43,7 +43,7 @@ class TimeMapperGetRangeStartAndEndTest { assertEquals( "Test failed for params $input", - output, + Range(output.first, output.second), subject.getRangeStartAndEnd( rangeLength = input[0] as RangeLength, shift = input[1] as Int, @@ -130,7 +130,7 @@ class TimeMapperGetRangeStartAndEndTest { assertEquals( "Test failed for params $input", - output, + Range(output.first, output.second), subject.getRangeStartAndEnd( rangeLength = input[0] as RangeLength, shift = input[1] as Int, @@ -301,7 +301,7 @@ class TimeMapperGetRangeStartAndEndTest { assertEquals( "Test failed for params $input", - output, + Range(output.first, output.second), subject.getRangeStartAndEnd( rangeLength = input[0] as RangeLength, shift = input[1] as Int, @@ -442,7 +442,7 @@ class TimeMapperGetRangeStartAndEndTest { assertEquals( "Test failed for params $input", - output, + Range(output.first, output.second), subject.getRangeStartAndEnd( rangeLength = input[0] as RangeLength, shift = input[1] as Int, @@ -583,7 +583,7 @@ class TimeMapperGetRangeStartAndEndTest { assertEquals( "Test failed for params $input", - output, + Range(output.first, output.second), subject.getRangeStartAndEnd( rangeLength = input[0] as RangeLength, shift = input[1] as Int, diff --git a/domain/src/main/java/com/example/util/simpletimetracker/domain/mapper/RangeMapper.kt b/domain/src/main/java/com/example/util/simpletimetracker/domain/mapper/RangeMapper.kt index f41d0158..f4a19a52 100644 --- a/domain/src/main/java/com/example/util/simpletimetracker/domain/mapper/RangeMapper.kt +++ b/domain/src/main/java/com/example/util/simpletimetracker/domain/mapper/RangeMapper.kt @@ -11,9 +11,9 @@ import kotlin.math.min class RangeMapper @Inject constructor() { fun getRecordsFromRange( - records: List, + records: List, range: Range, - ): List { + ): List { return records.filter { it.isInRange(range) } } @@ -25,25 +25,33 @@ class RangeMapper @Inject constructor() { } fun clampToRange( - record: Record, - rangeStart: Long, - rangeEnd: Long, + record: RecordBase, + range: Range, ): Range { return Range( - timeStarted = max(record.timeStarted, rangeStart), - timeEnded = min(record.timeEnded, rangeEnd) + timeStarted = max(record.timeStarted, range.timeStarted), + timeEnded = min(record.timeEnded, range.timeEnded) ) } fun clampRecordToRange( - record: Record, + record: RecordBase, range: Range, - ): Record { + ): RecordBase { return if (!record.isCompletelyRange(range)) { - record.copy( - timeStarted = max(record.timeStarted, range.timeStarted), - timeEnded = min(record.timeEnded, range.timeEnded) - ) + when (record) { + is Record -> record.copy( + timeStarted = max(record.timeStarted, range.timeStarted), + timeEnded = min(record.timeEnded, range.timeEnded) + ) + is RunningRecord -> Record( + typeId = record.typeId, + timeStarted = max(record.timeStarted, range.timeStarted), + timeEnded = min(record.timeEnded, range.timeEnded), + comment = record.comment, + tagIds = record.tagIds, + ) + } } else { record } @@ -59,7 +67,7 @@ class RangeMapper @Inject constructor() { return this.timeStarted < range.timeEnded && this.timeEnded > range.timeStarted } - private fun Record.isCompletelyRange( + private fun RecordBase.isCompletelyRange( range: Range, ): Boolean { return this.timeStarted >= range.timeStarted && this.timeEnded <= range.timeEnded diff --git a/domain/src/main/java/com/example/util/simpletimetracker/domain/mapper/UnCoveredRangesMapper.kt b/domain/src/main/java/com/example/util/simpletimetracker/domain/mapper/UnCoveredRangesMapper.kt index 86e0a6f0..dcf84b9e 100644 --- a/domain/src/main/java/com/example/util/simpletimetracker/domain/mapper/UnCoveredRangesMapper.kt +++ b/domain/src/main/java/com/example/util/simpletimetracker/domain/mapper/UnCoveredRangesMapper.kt @@ -1,5 +1,6 @@ package com.example.util.simpletimetracker.domain.mapper +import com.example.util.simpletimetracker.domain.model.Range import javax.inject.Inject import kotlin.math.max import kotlin.math.min @@ -12,7 +13,7 @@ class UnCoveredRangesMapper @Inject constructor() { * Implementation of Klee's algorithm for length of union of segments, * taken from here https://www.geeksforgeeks.org/klees-algorithm-length-union-segments-line/ */ - fun map(start: Long, end: Long, segments: List>): List> { + fun map(start: Long, end: Long, segments: List): List { if (start > end) return emptyList() val n = segments.size @@ -23,13 +24,13 @@ class UnCoveredRangesMapper @Inject constructor() { var secondIsHigher: Boolean for (i in (0 until n)) { // Ignore segments outside of range - if (segments[i].first < start && segments[i].second < start) continue - if (segments[i].first > end && segments[i].second > end) continue + if (segments[i].timeStarted < start && segments[i].timeEnded < start) continue + if (segments[i].timeStarted > end && segments[i].timeEnded > end) continue // Reverse segments if needed - secondIsHigher = segments[i].second > segments[i].first - points.add(max(start, segments[i].first) to !secondIsHigher) - points.add(min(end, segments[i].second) to secondIsHigher) + secondIsHigher = segments[i].timeEnded > segments[i].timeStarted + points.add(max(start, segments[i].timeStarted) to !secondIsHigher) + points.add(min(end, segments[i].timeEnded) to secondIsHigher) } // Sorting all points by point value @@ -40,7 +41,7 @@ class UnCoveredRangesMapper @Inject constructor() { points.add(end to false) // Initialize result - val result = mutableListOf>() + val result = mutableListOf() // To keep track of counts of current open segments // (Starting point is processed, but ending point is not) @@ -50,8 +51,8 @@ class UnCoveredRangesMapper @Inject constructor() { for (i in (1 until points.size)) { // If there are no open points, then we add the // difference between previous and current point. - if (counter == 0) (points[i - 1].first to points[i].first) - .takeUnless { it.first == it.second } + if (counter == 0) Range(points[i - 1].first, points[i].first) + .takeUnless { it.timeStarted == it.timeEnded } ?.let(result::add) // If this is an ending point, reduce count of open points diff --git a/domain/src/main/java/com/example/util/simpletimetracker/domain/mapper/UntrackedRecordMapper.kt b/domain/src/main/java/com/example/util/simpletimetracker/domain/mapper/UntrackedRecordMapper.kt index a0401692..bce38d5b 100644 --- a/domain/src/main/java/com/example/util/simpletimetracker/domain/mapper/UntrackedRecordMapper.kt +++ b/domain/src/main/java/com/example/util/simpletimetracker/domain/mapper/UntrackedRecordMapper.kt @@ -15,7 +15,7 @@ class UntrackedRecordMapper @Inject constructor( minStart: Long, maxEnd: Long, durationCutoff: Long, - ): List> { + ): List { val untrackedTimeStart = max(minStart, range.timeStarted) if (range.timeEnded < untrackedTimeStart) return emptyList() val untrackedTimeEndRange = min(maxEnd, range.timeEnded) @@ -23,10 +23,15 @@ class UntrackedRecordMapper @Inject constructor( return records // Remove parts of the record that are not in the range - .map { max(it.timeStarted, untrackedTimeStart) to min(it.timeEnded, untrackedTimeEndRange) } + .map { + Range( + max(it.timeStarted, untrackedTimeStart), + min(it.timeEnded, untrackedTimeEndRange) + ) + } // Calculate uncovered ranges .let { unCoveredRangesMapper.map(untrackedTimeStart, untrackedTimeEndRange, it) } - .filter { filter(it.second - it.first, durationCutoff) } + .filter { filter(it.duration, durationCutoff) } } fun filter( diff --git a/domain/src/main/java/com/example/util/simpletimetracker/domain/model/RecordBase.kt b/domain/src/main/java/com/example/util/simpletimetracker/domain/model/RecordBase.kt index 797aa87c..278799f1 100644 --- a/domain/src/main/java/com/example/util/simpletimetracker/domain/model/RecordBase.kt +++ b/domain/src/main/java/com/example/util/simpletimetracker/domain/model/RecordBase.kt @@ -1,6 +1,6 @@ package com.example.util.simpletimetracker.domain.model -interface RecordBase { +sealed interface RecordBase { val typeId: Long val timeStarted: Long val timeEnded: Long diff --git a/domain/src/test/java/com/example/util/simpletimetracker/domain/mapper/UnCoveredRangesMapperTest.kt b/domain/src/test/java/com/example/util/simpletimetracker/domain/mapper/UnCoveredRangesMapperTest.kt index 38ce8148..d89c3daa 100644 --- a/domain/src/test/java/com/example/util/simpletimetracker/domain/mapper/UnCoveredRangesMapperTest.kt +++ b/domain/src/test/java/com/example/util/simpletimetracker/domain/mapper/UnCoveredRangesMapperTest.kt @@ -1,5 +1,6 @@ package com.example.util.simpletimetracker.domain.mapper +import com.example.util.simpletimetracker.domain.model.Range import org.junit.Assert.assertEquals import org.junit.Test import org.junit.runner.RunWith @@ -8,7 +9,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) class UnCoveredRangesMapperTest( private val input: List, - private val output: List> + private val output: List ) { private val subject = UnCoveredRangesMapper() @@ -22,7 +23,7 @@ class UnCoveredRangesMapperTest( subject.map( start = input[0] as Long, end = input[1] as Long, - segments = input[2] as List> + segments = input[2] as List ) ) } @@ -33,107 +34,136 @@ class UnCoveredRangesMapperTest( fun data() = listOf( // Invalid range arrayOf( - listOf(10L, 0L, listOf(2L to 3L)), emptyList() + listOf(10L, 0L, listOf(Range(2L, 3L))), + emptyList() ), // Zero range arrayOf( - listOf(0L, 0L, listOf(2L to 3L)), emptyList() + listOf(0L, 0L, listOf(Range(2L, 3L))), + emptyList() ), // No segments arrayOf( - listOf(0L, 0L, emptyList>()), emptyList() + listOf(0L, 0L, emptyList()), + emptyList() ), arrayOf( - listOf(0L, 10L, emptyList>()), listOf(0L to 10L) + listOf(0L, 10L, emptyList()), + listOf(Range(0L, 10L)) ), // Zero segment arrayOf( - listOf(0L, 10L, listOf(2L to 2L)), listOf(0L to 2L, 2L to 10L) + listOf(0L, 10L, listOf(Range(2L, 2L))), + listOf(Range(0L, 2L), Range(2L, 10L)), ), arrayOf( - listOf(0L, 10L, listOf(0L to 0L, 5L to 5L, 10L to 10L)), listOf(0L to 5L, 5L to 10L) + listOf(0L, 10L, listOf(Range(0L, 0L), Range(5L, 5L), Range(10L, 10L))), + listOf(0L to 5L, Range(5L, 10L)) ), // Segments on range points arrayOf( - listOf(0L, 10L, listOf(0L to 10L)), emptyList() + listOf(0L, 10L, listOf(Range(0L, 10L))), + emptyList() ), arrayOf( - listOf(0L, 10L, listOf(0L to 2L, 8L to 10L)), listOf(2L to 8L) + listOf(0L, 10L, listOf(Range(0L, 2L), Range(8L, 10L))), + listOf(Range(2L, 8L)) ), arrayOf( - listOf(0L, 10L, listOf(0L to 6L, 4L to 10L)), emptyList() + listOf(0L, 10L, listOf(Range(0L, 6L), Range(4L, 10L))), + emptyList() ), arrayOf( - listOf(0L, 10L, listOf(0L to 5L, 5L to 10L)), emptyList() + listOf(0L, 10L, listOf(Range(0L, 5L), Range(5L, 10L))), + emptyList() ), // One segment arrayOf( - listOf(0L, 10L, listOf(2L to 3L)), listOf(0L to 2L, 3L to 10L) + listOf(0L, 10L, listOf(Range(2L, 3L))), + listOf(Range(0L, 2L), Range(3L, 10L)) ), arrayOf( - listOf(0L, 10L, listOf(3L to 2L)), listOf(0L to 2L, 3L to 10L) + listOf(0L, 10L, listOf(Range(3L, 2L))), + listOf(Range(0L, 2L), Range(3L, 10L)) ), arrayOf( - listOf(0L, 10L, listOf(0L to 2L)), listOf(2L to 10L) + listOf(0L, 10L, listOf(Range(0L, 2L))), + listOf(Range(2L, 10L)) ), arrayOf( - listOf(0L, 10L, listOf(7L to 10L)), listOf(0L to 7L) + listOf(0L, 10L, listOf(Range(7L, 10L))), + listOf(Range(0L, 7L)) ), // Overlapping segments arrayOf( - listOf(0L, 10L, listOf(2L to 3L, 2L to 3L)), listOf(0L to 2L, 3L to 10L) + listOf(0L, 10L, listOf(Range(2L, 3L), Range(2L, 3L))), + listOf(Range(0L, 2L), Range(3L, 10L)) ), arrayOf( - listOf(0L, 10L, listOf(2L to 3L, 2L to 4L)), listOf(0L to 2L, 4L to 10L) + listOf(0L, 10L, listOf(Range(2L, 3L), Range(2L, 4L))), + listOf(Range(0L, 2L), Range(4L, 10L)) ), arrayOf( - listOf(0L, 10L, listOf(3L to 2L, 2L to 4L)), listOf(0L to 2L, 4L to 10L) + listOf(0L, 10L, listOf(Range(3L, 2L), Range(2L, 4L))), + listOf(Range(0L, 2L), Range(4L, 10L)) ), arrayOf( - listOf(0L, 10L, listOf(2L to 4L, 4L to 2L)), listOf(0L to 2L, 4L to 10L) + listOf(0L, 10L, listOf(Range(2L, 4L), Range(4L, 2L))), + listOf(Range(0L, 2L), Range(4L, 10L)) ), arrayOf( - listOf(0L, 10L, listOf(2L to 5L, 1L to 6L)), listOf(0L to 1L, 6L to 10L) + listOf(0L, 10L, listOf(Range(2L, 5L), Range(1L, 6L))), + listOf(Range(0L, 1L), Range(6L, 10L)) ), arrayOf( - listOf(0L, 10L, listOf(2L to 5L, 4L to 8L)), listOf(0L to 2L, 8L to 10L) + listOf(0L, 10L, listOf(Range(2L, 5L), Range(4L, 8L))), + listOf(Range(0L, 2L), Range(8L, 10L)) ), arrayOf( - listOf(0L, 10L, listOf(1L to 2L, 2L to 4L, 4L to 7L)), listOf(0L to 1L, 7L to 10L) + listOf(0L, 10L, listOf(Range(1L, 2L), Range(2L, 4L), Range(4L, 7L))), + listOf(Range(0L, 1L), Range(7L, 10L)) ), arrayOf( - listOf(0L, 10L, listOf(0L to 3L, 3L to 6L, 6L to 10L)), emptyList() + listOf(0L, 10L, listOf(Range(0L, 3L), Range(3L, 6L), Range(6L, 10L))), + emptyList() ), // Disconnected segments arrayOf( - listOf(0L, 10L, listOf(2L to 5L, 8L to 9L)), (listOf(0L to 2L, 5L to 8L, 9L to 10L)) + listOf(0L, 10L, listOf(Range(2L, 5L), Range(8L, 9L))), + listOf(Range(0L, 2L), Range(5L, 8L), Range(9L, 10L)) ), arrayOf( - listOf(0L, 10L, listOf(0L to 5L, 8L to 10L)), (listOf(5L to 8L)) + listOf(0L, 10L, listOf(Range(0L, 5L), Range(8L, 10L))), + listOf(Range(5L, 8L)) ), // Outside of range arrayOf( - listOf(10L, 20L, listOf(5L to 6L)), (listOf(10L to 20L)) + listOf(10L, 20L, listOf(Range(5L, 6L))), + listOf(Range(10L, 20L)) ), arrayOf( - listOf(10L, 20L, listOf(4L to 6L, 24L to 26L)), (listOf(10L to 20L)) + listOf(10L, 20L, listOf(Range(4L, 6L), Range(24L, 26L))), + listOf(Range(10L, 20L)) ), arrayOf( - listOf(10L, 20L, listOf(4L to 16L)), (listOf(16L to 20L)) + listOf(10L, 20L, listOf(Range(4L, 16L))), + listOf(Range(16L, 20L)) ), arrayOf( - listOf(10L, 20L, listOf(4L to 14L, 16L to 26L)), (listOf(14L to 16L)) + listOf(10L, 20L, listOf(Range(4L, 14L), Range(16L, 26L))), + listOf(Range(14L, 16L)) ), arrayOf( - listOf(10L, 20L, listOf(4L to 16L, 14L to 26L)), emptyList() + listOf(10L, 20L, listOf(Range(4L, 16L), Range(14L, 26L))), + emptyList() ) ) } diff --git a/features/feature_change_running_record/src/main/java/com/example/util/simpletimetracker/feature_change_running_record/view/ChangeRunningRecordFragment.kt b/features/feature_change_running_record/src/main/java/com/example/util/simpletimetracker/feature_change_running_record/view/ChangeRunningRecordFragment.kt index 0ff1c498..a8a7c9e0 100644 --- a/features/feature_change_running_record/src/main/java/com/example/util/simpletimetracker/feature_change_running_record/view/ChangeRunningRecordFragment.kt +++ b/features/feature_change_running_record/src/main/java/com/example/util/simpletimetracker/feature_change_running_record/view/ChangeRunningRecordFragment.kt @@ -20,6 +20,7 @@ import com.example.util.simpletimetracker.feature_change_running_record.viewMode import com.example.util.simpletimetracker.feature_views.extension.setOnClick import com.example.util.simpletimetracker.navigation.Router import com.example.util.simpletimetracker.navigation.params.notification.SnackBarParams +import com.example.util.simpletimetracker.navigation.params.screen.ChangeRunningRecordFromScreen import com.example.util.simpletimetracker.navigation.params.screen.ChangeRunningRecordParams import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject @@ -166,8 +167,8 @@ class ChangeRunningRecordFragment : companion object { private const val ARGS_PARAMS = "args_running_record_params" - fun createBundle(data: ChangeRunningRecordParams): Bundle = Bundle().apply { - putParcelable(ARGS_PARAMS, data) + fun createBundle(data: ChangeRunningRecordFromScreen): Bundle = Bundle().apply { + putParcelable(ARGS_PARAMS, data.params) } } } \ No newline at end of file diff --git a/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/interactor/DateEditChangeInteractor.kt b/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/interactor/DateEditChangeInteractor.kt index 663d3554..6eeb6b23 100644 --- a/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/interactor/DateEditChangeInteractor.kt +++ b/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/interactor/DateEditChangeInteractor.kt @@ -6,6 +6,7 @@ import com.example.util.simpletimetracker.domain.interactor.NotificationGoalTime import com.example.util.simpletimetracker.domain.interactor.RecordInteractor import com.example.util.simpletimetracker.domain.interactor.RecordTagInteractor import com.example.util.simpletimetracker.domain.interactor.RemoveRecordMediator +import com.example.util.simpletimetracker.domain.model.Record import com.example.util.simpletimetracker.domain.model.RecordsFilter import com.example.util.simpletimetracker.feature_base_adapter.category.CategoryViewData import com.example.util.simpletimetracker.feature_data_edit.model.DataEditAddTagsState @@ -53,6 +54,7 @@ class DateEditChangeInteractor @Inject constructor( ) return val records = recordFilterInteractor.getByFilter(filters) + .filterIsInstance() val tags = recordTagInteractor.getAll().associateBy { it.id } val oldTypeIds = mutableSetOf() diff --git a/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/interactor/DateEditViewDataInteractor.kt b/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/interactor/DateEditViewDataInteractor.kt index 3b8d8f24..dffb7b04 100644 --- a/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/interactor/DateEditViewDataInteractor.kt +++ b/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/interactor/DateEditViewDataInteractor.kt @@ -8,6 +8,7 @@ import com.example.util.simpletimetracker.domain.extension.orZero import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor import com.example.util.simpletimetracker.domain.interactor.RecordTagInteractor import com.example.util.simpletimetracker.domain.interactor.RecordTypeInteractor +import com.example.util.simpletimetracker.domain.model.Record import com.example.util.simpletimetracker.domain.model.RecordTag import com.example.util.simpletimetracker.domain.model.RecordsFilter import com.example.util.simpletimetracker.feature_base_adapter.category.CategoryViewData @@ -32,6 +33,7 @@ class DateEditViewDataInteractor @Inject constructor( filters: List, ): DataEditRecordsCountState { val records = recordFilterInteractor.getByFilter(filters) + .filterIsInstance() val selectedRecordsCount = records.size val recordsString = resourceRepo.getQuantityString( R.plurals.statistics_detail_times_tracked, diff --git a/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/viewModel/DataEditViewModel.kt b/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/viewModel/DataEditViewModel.kt index 9cbff996..29c1fea3 100644 --- a/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/viewModel/DataEditViewModel.kt +++ b/features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/viewModel/DataEditViewModel.kt @@ -96,6 +96,7 @@ class DataEditViewModel @Inject constructor( title = resourceRepo.getString(R.string.chart_filter_hint), dateSelectionAvailable = true, untrackedSelectionAvailable = false, + addRunningRecords = false, filters = filters.map(RecordsFilter::toParams), ).let(router::navigate) } diff --git a/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/core/GetTimeToDayEndInteractor.kt b/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/core/GetTimeToDayEndInteractor.kt index 63fdaed2..7e731c61 100644 --- a/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/core/GetTimeToDayEndInteractor.kt +++ b/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/core/GetTimeToDayEndInteractor.kt @@ -19,7 +19,7 @@ class GetTimeToDayEndInteractor @Inject constructor( firstDayOfWeek = DayOfWeek.MONDAY, // not needed. startOfDayShift = 0, // not needed. ) - .second + .timeEnded .let { it - current } .takeIf { it > 0 } ?: current diff --git a/features/feature_records/src/main/java/com/example/util/simpletimetracker/feature_records/interactor/RecordsViewDataInteractor.kt b/features/feature_records/src/main/java/com/example/util/simpletimetracker/feature_records/interactor/RecordsViewDataInteractor.kt index 5a89cbae..aebeca04 100644 --- a/features/feature_records/src/main/java/com/example/util/simpletimetracker/feature_records/interactor/RecordsViewDataInteractor.kt +++ b/features/feature_records/src/main/java/com/example/util/simpletimetracker/feature_records/interactor/RecordsViewDataInteractor.kt @@ -64,21 +64,20 @@ class RecordsViewDataInteractor @Inject constructor( return@withContext (daysCountInShift - 1 downTo 0).map { dayInShift -> val actualShift = shift * daysCountInShift - dayInShift - val (rangeStart, rangeEnd) = timeMapper.getRangeStartAndEnd( + val range = timeMapper.getRangeStartAndEnd( rangeLength = RangeLength.Day, shift = actualShift, firstDayOfWeek = DayOfWeek.MONDAY, // Doesn't matter for days. startOfDayShift = startOfDayShift, ) - val records = recordInteractor.getFromRange(Range(rangeStart, rangeEnd)) + val records = recordInteractor.getFromRange(range) val data = getRecordsViewData( records = records, runningRecords = runningRecords, recordTypes = recordTypes, recordTags = recordTags, - rangeStart = rangeStart, - rangeEnd = rangeEnd, + range = range, isDarkTheme = isDarkTheme, useMilitaryTime = useMilitaryTime, useProportionalMinutes = useProportionalMinutes, @@ -87,8 +86,8 @@ class RecordsViewDataInteractor @Inject constructor( ) ViewDataIntermediate( - rangeStart = rangeStart, - rangeEnd = rangeEnd, + rangeStart = range.timeStarted, + rangeEnd = range.timeEnded, records = data, ) }.let { data -> @@ -169,8 +168,7 @@ class RecordsViewDataInteractor @Inject constructor( runningRecords: List, recordTypes: Map, recordTags: List, - rangeStart: Long, - rangeEnd: Long, + range: Range, isDarkTheme: Boolean, useMilitaryTime: Boolean, useProportionalMinutes: Boolean, @@ -183,8 +181,7 @@ class RecordsViewDataInteractor @Inject constructor( record = record, recordType = recordTypes[record.typeId] ?: return@mapNotNull null, recordTags = recordTags.filter { it.id in record.tagIds }, - rangeStart = rangeStart, - rangeEnd = rangeEnd, + range = range, isDarkTheme = isDarkTheme, useMilitaryTime = useMilitaryTime, useProportionalMinutes = useProportionalMinutes, @@ -199,10 +196,7 @@ class RecordsViewDataInteractor @Inject constructor( val runningRecordsData = runningRecords .let { - rangeMapper.getRunningRecordsFromRange( - records = it, - range = Range(rangeStart, rangeEnd), - ) + rangeMapper.getRunningRecordsFromRange(it, range,) } .mapNotNull { runningRecord -> getRunningRecordViewDataMediator.execute( @@ -234,17 +228,16 @@ class RecordsViewDataInteractor @Inject constructor( val runningRecordRanges = runningRecords.map { Range( timeStarted = it.timeStarted, - timeEnded = System.currentTimeMillis(), + timeEnded = it.timeEnded, ) } getUntrackedRecordsInteractor.get( - range = Range(rangeStart, rangeEnd), + range = range, records = recordRanges + runningRecordRanges, ).map { untrackedRecord -> recordsViewDataMapper.mapToUntracked( record = untrackedRecord, - rangeStart = rangeStart, - rangeEnd = rangeEnd, + range = range, isDarkTheme = isDarkTheme, useMilitaryTime = useMilitaryTime, useProportionalMinutes = useProportionalMinutes, diff --git a/features/feature_records/src/main/java/com/example/util/simpletimetracker/feature_records/mapper/RecordsViewDataMapper.kt b/features/feature_records/src/main/java/com/example/util/simpletimetracker/feature_records/mapper/RecordsViewDataMapper.kt index a997dbd4..0261b6ae 100644 --- a/features/feature_records/src/main/java/com/example/util/simpletimetracker/feature_records/mapper/RecordsViewDataMapper.kt +++ b/features/feature_records/src/main/java/com/example/util/simpletimetracker/feature_records/mapper/RecordsViewDataMapper.kt @@ -3,6 +3,7 @@ package com.example.util.simpletimetracker.feature_records.mapper import com.example.util.simpletimetracker.core.mapper.RecordViewDataMapper import com.example.util.simpletimetracker.core.mapper.TimeMapper import com.example.util.simpletimetracker.core.repo.ResourceRepo +import com.example.util.simpletimetracker.domain.model.Range import com.example.util.simpletimetracker.domain.model.Record import com.example.util.simpletimetracker.domain.model.RecordTag import com.example.util.simpletimetracker.domain.model.RecordType @@ -25,14 +26,13 @@ class RecordsViewDataMapper @Inject constructor( record: Record, recordType: RecordType, recordTags: List, - rangeStart: Long, - rangeEnd: Long, + range: Range, isDarkTheme: Boolean, useMilitaryTime: Boolean, useProportionalMinutes: Boolean, showSeconds: Boolean, ): RecordViewData.Tracked { - val (timeStarted, timeEnded) = clampToRange(record, rangeStart, rangeEnd) + val (timeStarted, timeEnded) = clampToRange(record, range) return recordViewDataMapper.map( record = record, @@ -49,14 +49,13 @@ class RecordsViewDataMapper @Inject constructor( fun mapToUntracked( record: Record, - rangeStart: Long, - rangeEnd: Long, + range: Range, isDarkTheme: Boolean, useMilitaryTime: Boolean, useProportionalMinutes: Boolean, showSeconds: Boolean, ): RecordViewData.Untracked { - val (timeStarted, timeEnded) = clampToRange(record, rangeStart, rangeEnd) + val (timeStarted, timeEnded) = clampToRange(record, range) return recordViewDataMapper.mapToUntracked( timeStarted = timeStarted, @@ -100,20 +99,19 @@ class RecordsViewDataMapper @Inject constructor( private fun clampToRange( record: Record, - rangeStart: Long, - rangeEnd: Long, - ): Pair { - val timeStarted = if (rangeStart != 0L) { - max(record.timeStarted, rangeStart) + range: Range, + ): Range { + val timeStarted = if (range.timeStarted != 0L) { + max(record.timeStarted, range.timeStarted) } else { record.timeStarted } - val timeEnded = if (rangeEnd != 0L) { - min(record.timeEnded, rangeEnd) + val timeEnded = if (range.timeEnded != 0L) { + min(record.timeEnded, range.timeEnded) } else { record.timeEnded } - return timeStarted to timeEnded + return Range(timeStarted, timeEnded) } } \ No newline at end of file diff --git a/features/feature_records/src/main/java/com/example/util/simpletimetracker/feature_records/viewModel/RecordsViewModel.kt b/features/feature_records/src/main/java/com/example/util/simpletimetracker/feature_records/viewModel/RecordsViewModel.kt index bae2c394..0edb8403 100644 --- a/features/feature_records/src/main/java/com/example/util/simpletimetracker/feature_records/viewModel/RecordsViewModel.kt +++ b/features/feature_records/src/main/java/com/example/util/simpletimetracker/feature_records/viewModel/RecordsViewModel.kt @@ -21,6 +21,7 @@ import com.example.util.simpletimetracker.feature_records.model.RecordsState import com.example.util.simpletimetracker.navigation.Router import com.example.util.simpletimetracker.navigation.params.screen.ChangeRecordFromMainParams import com.example.util.simpletimetracker.navigation.params.screen.ChangeRecordParams +import com.example.util.simpletimetracker.navigation.params.screen.ChangeRunningRecordFromMainParams import com.example.util.simpletimetracker.navigation.params.screen.ChangeRunningRecordParams import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @@ -58,26 +59,27 @@ class RecordsViewModel @Inject constructor( } fun onRunningRecordClick(item: RunningRecordViewData, sharedElements: Pair? = null) { + val params = ChangeRunningRecordParams( + transitionName = sharedElements?.second.orEmpty(), + id = item.id, + from = ChangeRunningRecordParams.From.Records, + preview = ChangeRunningRecordParams.Preview( + name = item.name, + tagName = item.tagName, + timeStarted = item.timeStarted, + duration = item.timer, + durationTotal = item.timerTotal, + goalTime = item.goalTime.toParams(), + goalTime2 = item.goalTime2.toParams(), + goalTime3 = item.goalTime3.toParams(), + goalTime4 = item.goalTime4.toParams(), + iconId = item.iconId.toParams(), + color = item.color, + comment = item.comment + ) + ) router.navigate( - data = ChangeRunningRecordParams( - transitionName = sharedElements?.second.orEmpty(), - id = item.id, - from = ChangeRunningRecordParams.From.Records, - preview = ChangeRunningRecordParams.Preview( - name = item.name, - tagName = item.tagName, - timeStarted = item.timeStarted, - duration = item.timer, - durationTotal = item.timerTotal, - goalTime = item.goalTime.toParams(), - goalTime2 = item.goalTime2.toParams(), - goalTime3 = item.goalTime3.toParams(), - goalTime4 = item.goalTime4.toParams(), - iconId = item.iconId.toParams(), - color = item.color, - comment = item.comment - ) - ), + data = ChangeRunningRecordFromMainParams(params), sharedElements = sharedElements?.let(::mapOf) ?: emptyMap() ) } diff --git a/features/feature_records_all/src/main/java/com/example/util/simpletimetracker/feature_records_all/interactor/RecordsAllViewDataInteractor.kt b/features/feature_records_all/src/main/java/com/example/util/simpletimetracker/feature_records_all/interactor/RecordsAllViewDataInteractor.kt index e0563e5f..6b0e0277 100644 --- a/features/feature_records_all/src/main/java/com/example/util/simpletimetracker/feature_records_all/interactor/RecordsAllViewDataInteractor.kt +++ b/features/feature_records_all/src/main/java/com/example/util/simpletimetracker/feature_records_all/interactor/RecordsAllViewDataInteractor.kt @@ -1,12 +1,15 @@ package com.example.util.simpletimetracker.feature_records_all.interactor +import com.example.util.simpletimetracker.core.interactor.GetRunningRecordViewDataMediator import com.example.util.simpletimetracker.core.interactor.RecordFilterInteractor import com.example.util.simpletimetracker.core.mapper.DateDividerViewDataMapper import com.example.util.simpletimetracker.core.mapper.RecordViewDataMapper import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor import com.example.util.simpletimetracker.domain.interactor.RecordTagInteractor import com.example.util.simpletimetracker.domain.interactor.RecordTypeInteractor +import com.example.util.simpletimetracker.domain.model.Record import com.example.util.simpletimetracker.domain.model.RecordsFilter +import com.example.util.simpletimetracker.domain.model.RunningRecord import com.example.util.simpletimetracker.feature_base_adapter.ViewHolderType import com.example.util.simpletimetracker.feature_records_all.model.RecordsAllSortOrder import javax.inject.Inject @@ -19,6 +22,7 @@ class RecordsAllViewDataInteractor @Inject constructor( private val prefsInteractor: PrefsInteractor, private val recordFilterInteractor: RecordFilterInteractor, private val recordViewDataMapper: RecordViewDataMapper, + private val getRunningRecordViewDataMediator: GetRunningRecordViewDataMediator, private val dateDividerViewDataMapper: DateDividerViewDataMapper, ) { @@ -43,17 +47,31 @@ class RecordsAllViewDataInteractor @Inject constructor( .map { record -> val type = recordTypes[record.typeId] val viewData = if (type != null) { - recordViewDataMapper.map( - record = record, - recordType = type, - recordTags = recordTags.filter { it.id in record.tagIds }, - timeStarted = record.timeStarted, - timeEnded = record.timeEnded, - isDarkTheme = isDarkTheme, - useMilitaryTime = useMilitaryTime, - useProportionalMinutes = useProportionalMinutes, - showSeconds = showSeconds, - ) + when (record) { + is Record -> recordViewDataMapper.map( + record = record, + recordType = type, + recordTags = recordTags.filter { it.id in record.tagIds }, + timeStarted = record.timeStarted, + timeEnded = record.timeEnded, + isDarkTheme = isDarkTheme, + useMilitaryTime = useMilitaryTime, + useProportionalMinutes = useProportionalMinutes, + showSeconds = showSeconds, + ) + is RunningRecord -> getRunningRecordViewDataMediator.execute( + type = type, + tags = recordTags.filter { it.id in record.tagIds }, + record = record, + nowIconVisible = true, + goalsVisible = false, + totalDurationVisible = false, + isDarkTheme = isDarkTheme, + useMilitaryTime = useMilitaryTime, + useProportionalMinutes = useProportionalMinutes, + showSeconds = showSeconds, + ) + } } else { recordViewDataMapper.mapToUntracked( timeStarted = record.timeStarted, diff --git a/features/feature_records_all/src/main/java/com/example/util/simpletimetracker/feature_records_all/view/RecordsAllFragment.kt b/features/feature_records_all/src/main/java/com/example/util/simpletimetracker/feature_records_all/view/RecordsAllFragment.kt index 209bfc91..7dcb4598 100644 --- a/features/feature_records_all/src/main/java/com/example/util/simpletimetracker/feature_records_all/view/RecordsAllFragment.kt +++ b/features/feature_records_all/src/main/java/com/example/util/simpletimetracker/feature_records_all/view/RecordsAllFragment.kt @@ -16,8 +16,10 @@ import com.example.util.simpletimetracker.feature_base_adapter.empty.createEmpty import com.example.util.simpletimetracker.feature_base_adapter.loader.createLoaderAdapterDelegate import com.example.util.simpletimetracker.feature_base_adapter.record.createRecordAdapterDelegate import com.example.util.simpletimetracker.feature_base_adapter.recordsDateDivider.createRecordsDateDividerAdapterDelegate +import com.example.util.simpletimetracker.feature_base_adapter.runningRecord.createRunningRecordAdapterDelegate import com.example.util.simpletimetracker.feature_records_all.viewData.RecordsAllSortOrderViewData import com.example.util.simpletimetracker.feature_records_all.viewModel.RecordsAllViewModel +import com.example.util.simpletimetracker.feature_views.TransitionNames import com.example.util.simpletimetracker.navigation.Router import com.example.util.simpletimetracker.navigation.params.notification.SnackBarParams import com.example.util.simpletimetracker.navigation.params.screen.RecordsAllParams @@ -42,6 +44,10 @@ class RecordsAllFragment : BaseFragment() { ) private val recordsAdapter: BaseRecyclerAdapter by lazy { BaseRecyclerAdapter( + createRunningRecordAdapterDelegate( + transitionNamePrefix = TransitionNames.RUNNING_RECORD_FROM_RECORDS, + onItemClick = throttle(viewModel::onRunningRecordClick), + ), createRecordAdapterDelegate(throttle(viewModel::onRecordClick)), createRecordsDateDividerAdapterDelegate(), createEmptyAdapterDelegate(), diff --git a/features/feature_records_all/src/main/java/com/example/util/simpletimetracker/feature_records_all/viewModel/RecordsAllViewModel.kt b/features/feature_records_all/src/main/java/com/example/util/simpletimetracker/feature_records_all/viewModel/RecordsAllViewModel.kt index 45358a8c..4f4e6143 100644 --- a/features/feature_records_all/src/main/java/com/example/util/simpletimetracker/feature_records_all/viewModel/RecordsAllViewModel.kt +++ b/features/feature_records_all/src/main/java/com/example/util/simpletimetracker/feature_records_all/viewModel/RecordsAllViewModel.kt @@ -10,6 +10,7 @@ import com.example.util.simpletimetracker.core.extension.toParams import com.example.util.simpletimetracker.feature_base_adapter.ViewHolderType import com.example.util.simpletimetracker.feature_base_adapter.loader.LoaderViewData import com.example.util.simpletimetracker.feature_base_adapter.record.RecordViewData +import com.example.util.simpletimetracker.feature_base_adapter.runningRecord.RunningRecordViewData import com.example.util.simpletimetracker.feature_records_all.interactor.RecordsAllViewDataInteractor import com.example.util.simpletimetracker.feature_records_all.mapper.RecordsAllViewDataMapper import com.example.util.simpletimetracker.feature_records_all.model.RecordsAllSortOrder @@ -17,6 +18,8 @@ import com.example.util.simpletimetracker.feature_records_all.viewData.RecordsAl import com.example.util.simpletimetracker.navigation.Router import com.example.util.simpletimetracker.navigation.params.screen.ChangeRecordFromRecordsAllParams import com.example.util.simpletimetracker.navigation.params.screen.ChangeRecordParams +import com.example.util.simpletimetracker.navigation.params.screen.ChangeRunningRecordFromRecordsAllParams +import com.example.util.simpletimetracker.navigation.params.screen.ChangeRunningRecordParams import com.example.util.simpletimetracker.navigation.params.screen.RecordsAllParams import com.example.util.simpletimetracker.navigation.params.screen.RecordsFilterParam import dagger.hilt.android.lifecycle.HiltViewModel @@ -51,29 +54,65 @@ class RecordsAllViewModel @Inject constructor( private var sortOrder: RecordsAllSortOrder = RecordsAllSortOrder.TIME_STARTED + fun onRunningRecordClick( + item: RunningRecordViewData, + sharedElements: Pair, + ) { + val params = ChangeRunningRecordParams( + transitionName = sharedElements.second, + id = item.id, + from = ChangeRunningRecordParams.From.Records, + preview = ChangeRunningRecordParams.Preview( + name = item.name, + tagName = item.tagName, + timeStarted = item.timeStarted, + duration = item.timer, + durationTotal = item.timerTotal, + goalTime = item.goalTime.toParams(), + goalTime2 = item.goalTime2.toParams(), + goalTime3 = item.goalTime3.toParams(), + goalTime4 = item.goalTime4.toParams(), + iconId = item.iconId.toParams(), + color = item.color, + comment = item.comment + ) + ) + router.navigate( + data = ChangeRunningRecordFromRecordsAllParams(params), + sharedElements = mapOf(sharedElements) + ) + } + fun onRecordClick(item: RecordViewData, sharedElements: Pair) { - if (item is RecordViewData.Tracked) { - ChangeRecordParams.Tracked( + val preview = ChangeRecordParams.Preview( + name = item.name, + tagName = item.tagName, + timeStarted = item.timeStarted, + timeFinished = item.timeFinished, + duration = item.duration, + iconId = item.iconId.toParams(), + color = item.color, + comment = item.comment + ) + + val params = when (item) { + is RecordViewData.Tracked -> ChangeRecordParams.Tracked( transitionName = sharedElements.second, id = item.id, from = ChangeRecordParams.From.RecordsAll, - preview = ChangeRecordParams.Preview( - name = item.name, - tagName = item.tagName, - timeStarted = item.timeStarted, - timeFinished = item.timeFinished, - duration = item.duration, - iconId = item.iconId.toParams(), - color = item.color, - comment = item.comment - ) - ).let { params -> - router.navigate( - data = ChangeRecordFromRecordsAllParams(params), - sharedElements = mapOf(sharedElements) - ) - } + preview = preview, + ) + is RecordViewData.Untracked -> ChangeRecordParams.Untracked( + transitionName = sharedElements.second, + timeStarted = item.timeStartedTimestamp, + timeEnded = item.timeEndedTimestamp, + preview = preview + ) } + router.navigate( + data = ChangeRecordFromRecordsAllParams(params), + sharedElements = mapOf(sharedElements) + ) } fun onVisible() { diff --git a/features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/interactor/RecordsFilterViewDataInteractor.kt b/features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/interactor/RecordsFilterViewDataInteractor.kt index df68d0f6..52f810c6 100644 --- a/features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/interactor/RecordsFilterViewDataInteractor.kt +++ b/features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/interactor/RecordsFilterViewDataInteractor.kt @@ -1,6 +1,7 @@ package com.example.util.simpletimetracker.feature_records_filter.interactor import com.example.util.simpletimetracker.core.extension.setToStartOfDay +import com.example.util.simpletimetracker.core.interactor.GetRunningRecordViewDataMediator import com.example.util.simpletimetracker.core.interactor.RecordFilterInteractor import com.example.util.simpletimetracker.core.mapper.CategoryViewDataMapper import com.example.util.simpletimetracker.core.mapper.ColorMapper @@ -37,6 +38,7 @@ import com.example.util.simpletimetracker.domain.model.RecordTag import com.example.util.simpletimetracker.domain.model.RecordType import com.example.util.simpletimetracker.domain.model.RecordTypeCategory import com.example.util.simpletimetracker.domain.model.RecordsFilter +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.divider.DividerViewData import com.example.util.simpletimetracker.feature_base_adapter.hint.HintViewData @@ -67,6 +69,7 @@ class RecordsFilterViewDataInteractor @Inject constructor( private val recordTypeViewDataMapper: RecordTypeViewDataMapper, private val categoryViewDataMapper: CategoryViewDataMapper, private val recordViewDataMapper: RecordViewDataMapper, + private val getRunningRecordViewDataMediator: GetRunningRecordViewDataMediator, private val dateDividerViewDataMapper: DateDividerViewDataMapper, private val colorMapper: ColorMapper, private val timeMapper: TimeMapper, @@ -134,6 +137,7 @@ class RecordsFilterViewDataInteractor @Inject constructor( } .orEmpty() val records = recordFilterInteractor.getByFilter(finalFilters) + .let { if (extra.addRunningRecords) it else it.filterIsInstance() } val manuallyFilteredRecords = filters .getManuallyFilteredRecordIds() .mapNotNull { recordInteractor.get(it) } // TODO do better @@ -156,17 +160,31 @@ class RecordsFilterViewDataInteractor @Inject constructor( .map { record -> val type = recordTypes[record.typeId] val viewData = if (type != null) { - recordViewDataMapper.map( - record = record, - recordType = type, - recordTags = recordTags.filter { it.id in record.tagIds }, - timeStarted = record.timeStarted, - timeEnded = record.timeEnded, - isDarkTheme = isDarkTheme, - useMilitaryTime = useMilitaryTime, - useProportionalMinutes = useProportionalMinutes, - showSeconds = showSeconds, - ) + when (record) { + is Record -> recordViewDataMapper.map( + record = record, + recordType = type, + recordTags = recordTags.filter { it.id in record.tagIds }, + timeStarted = record.timeStarted, + timeEnded = record.timeEnded, + isDarkTheme = isDarkTheme, + useMilitaryTime = useMilitaryTime, + useProportionalMinutes = useProportionalMinutes, + showSeconds = showSeconds, + ) + is RunningRecord -> getRunningRecordViewDataMediator.execute( + type = type, + tags = recordTags.filter { it.id in record.tagIds }, + record = record, + nowIconVisible = true, + goalsVisible = false, + totalDurationVisible = false, + isDarkTheme = isDarkTheme, + useMilitaryTime = useMilitaryTime, + useProportionalMinutes = useProportionalMinutes, + showSeconds = showSeconds, + ) + } } else { recordViewDataMapper.mapToUntracked( timeStarted = record.timeStarted, 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 7d02b753..c0da2a38 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 @@ -29,6 +29,7 @@ import com.example.util.simpletimetracker.feature_base_adapter.record.createReco import com.example.util.simpletimetracker.feature_base_adapter.recordFilter.createRecordFilterAdapterDelegate import com.example.util.simpletimetracker.feature_base_adapter.recordType.createRecordTypeAdapterDelegate import com.example.util.simpletimetracker.feature_base_adapter.recordsDateDivider.createRecordsDateDividerAdapterDelegate +import com.example.util.simpletimetracker.feature_base_adapter.runningRecord.createRunningRecordAdapterDelegate import com.example.util.simpletimetracker.feature_records_filter.adapter.createRecordsFilterButtonAdapterDelegate import com.example.util.simpletimetracker.feature_records_filter.adapter.createRecordsFilterCommentAdapterDelegate import com.example.util.simpletimetracker.feature_records_filter.adapter.createRecordsFilterDayOfWeekAdapterDelegate @@ -87,6 +88,7 @@ class RecordsFilterFragment : createLoaderAdapterDelegate(), createEmptyAdapterDelegate(), createRecordsDateDividerAdapterDelegate(), + createRunningRecordAdapterDelegate("", { _, _ -> }), createRecordAdapterDelegate(viewModel::onRecordClick) ) } diff --git a/features/feature_settings/src/main/java/com/example/util/simpletimetracker/feature_settings/viewModel/SettingsViewModel.kt b/features/feature_settings/src/main/java/com/example/util/simpletimetracker/feature_settings/viewModel/SettingsViewModel.kt index 51cb2d4e..68be4cbb 100644 --- a/features/feature_settings/src/main/java/com/example/util/simpletimetracker/feature_settings/viewModel/SettingsViewModel.kt +++ b/features/feature_settings/src/main/java/com/example/util/simpletimetracker/feature_settings/viewModel/SettingsViewModel.kt @@ -487,6 +487,7 @@ class SettingsViewModel @Inject constructor( val newValue = prefsInteractor.getStartOfDayShift() * -1 prefsInteractor.setStartOfDayShift(newValue) widgetInteractor.updateWidgets(listOf(WidgetType.STATISTICS_CHART)) + notificationTypeInteractor.updateNotifications() notificationGoalTimeInteractor.checkAndReschedule() updateStartOfDayViewData() } @@ -844,6 +845,7 @@ class SettingsViewModel @Inject constructor( val newValue = settingsMapper.toStartOfDayShift(timestamp, wasPositive) prefsInteractor.setStartOfDayShift(newValue) widgetInteractor.updateWidgets(listOf(WidgetType.STATISTICS_CHART)) + notificationTypeInteractor.updateNotifications() notificationGoalTimeInteractor.checkAndReschedule() updateStartOfDayViewData() } diff --git a/features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/interactor/StatisticsDetailChartInteractor.kt b/features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/interactor/StatisticsDetailChartInteractor.kt index 0c1698b4..79f22803 100644 --- a/features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/interactor/StatisticsDetailChartInteractor.kt +++ b/features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/interactor/StatisticsDetailChartInteractor.kt @@ -2,16 +2,16 @@ package com.example.util.simpletimetracker.feature_statistics_detail.interactor import com.example.util.simpletimetracker.core.extension.setToStartOfDay import com.example.util.simpletimetracker.core.extension.setWeekToFirstDay -import com.example.util.simpletimetracker.domain.mapper.RangeMapper import com.example.util.simpletimetracker.core.mapper.TimeMapper import com.example.util.simpletimetracker.domain.extension.getTypeIds import com.example.util.simpletimetracker.domain.extension.hasActivityFilter import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor import com.example.util.simpletimetracker.domain.interactor.RecordTypeInteractor +import com.example.util.simpletimetracker.domain.mapper.RangeMapper import com.example.util.simpletimetracker.domain.model.DayOfWeek 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.RecordBase import com.example.util.simpletimetracker.domain.model.RecordsFilter import com.example.util.simpletimetracker.feature_statistics_detail.mapper.StatisticsDetailViewDataMapper import com.example.util.simpletimetracker.feature_statistics_detail.model.ChartBarDataDuration @@ -35,8 +35,8 @@ class StatisticsDetailChartInteractor @Inject constructor( ) { suspend fun getChartViewData( - records: List, - compareRecords: List, + records: List, + compareRecords: List, filter: List, compare: List, currentChartGrouping: ChartGrouping, @@ -125,7 +125,7 @@ class StatisticsDetailChartInteractor @Inject constructor( } private fun getChartData( - allRecords: List, + allRecords: List, ranges: List, ): List { fun mapEmpty(): List { @@ -144,8 +144,9 @@ class StatisticsDetailChartInteractor @Inject constructor( return ranges .map { data -> - val duration = rangeMapper.getRecordsFromRange(records, Range(data.rangeStart, data.rangeEnd)) - .map { record -> rangeMapper.clampToRange(record, data.rangeStart, data.rangeEnd) } + val range = Range(data.rangeStart, data.rangeEnd) + val duration = rangeMapper.getRecordsFromRange(records, range) + .map { record -> rangeMapper.clampToRange(record, range) } .let(rangeMapper::mapToDuration) ChartBarDataDuration( @@ -209,7 +210,7 @@ class StatisticsDetailChartInteractor @Inject constructor( is RangeLength.Last, -> timeMapper.getRangeStartAndEnd( rangeLength, rangePosition, firstDayOfWeek, 0 - ).second - 1 + ).timeEnded - 1 is RangeLength.All -> System.currentTimeMillis() is RangeLength.Custom -> rangeLength.range.timeEnded - 1 } diff --git a/features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/interactor/StatisticsDetailSplitChartInteractor.kt b/features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/interactor/StatisticsDetailSplitChartInteractor.kt index 6715584d..fc254bb0 100644 --- a/features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/interactor/StatisticsDetailSplitChartInteractor.kt +++ b/features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/interactor/StatisticsDetailSplitChartInteractor.kt @@ -1,12 +1,12 @@ package com.example.util.simpletimetracker.feature_statistics_detail.interactor -import com.example.util.simpletimetracker.domain.mapper.RangeMapper import com.example.util.simpletimetracker.core.mapper.TimeMapper import com.example.util.simpletimetracker.domain.extension.orZero import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor +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.RecordBase import com.example.util.simpletimetracker.domain.model.RecordsFilter import com.example.util.simpletimetracker.feature_statistics_detail.mapper.StatisticsDetailViewDataMapper import com.example.util.simpletimetracker.feature_statistics_detail.model.SplitChartGrouping @@ -28,7 +28,7 @@ class StatisticsDetailSplitChartInteractor @Inject constructor( ) { suspend fun getSplitChartViewData( - records: List, + records: List, filter: List, isForComparison: Boolean, rangeLength: RangeLength, @@ -59,7 +59,7 @@ class StatisticsDetailSplitChartInteractor @Inject constructor( } suspend fun getDurationSplitViewData( - records: List, + records: List, filter: List, isForComparison: Boolean, rangeLength: RangeLength, @@ -74,19 +74,9 @@ class StatisticsDetailSplitChartInteractor @Inject constructor( startOfDayShift = startOfDayShift ) - val ranges = if (range.first != 0L && range.second != 0L) { - rangeMapper - .getRecordsFromRange( - records = records, - range = Range(range.first, range.second), - ) - .map { - rangeMapper.clampToRange( - record = it, - rangeStart = range.first, - rangeEnd = range.second - ) - } + val ranges = if (range.timeStarted != 0L && range.timeEnded != 0L) { + rangeMapper.getRecordsFromRange(records, range) + .map { rangeMapper.clampToRange(it, range) } } else { records.map { Range(it.timeStarted, it.timeEnded) } } @@ -152,8 +142,8 @@ class StatisticsDetailSplitChartInteractor @Inject constructor( } private fun getDurations( - records: List, - range: Pair, + records: List, + range: Range, splitChartGrouping: SplitChartGrouping, startOfDayShift: Long, ): Map { @@ -181,10 +171,10 @@ class StatisticsDetailSplitChartInteractor @Inject constructor( } } - private fun mapToRanges(records: List, range: Pair): List { - return if (range.first != 0L && range.second != 0L) { - rangeMapper.getRecordsFromRange(records, Range(range.first, range.second)) - .map { rangeMapper.clampToRange(it, range.first, range.second) } + private fun mapToRanges(records: List, range: Range): List { + return if (range.timeStarted != 0L && range.timeEnded != 0L) { + rangeMapper.getRecordsFromRange(records, range) + .map { rangeMapper.clampToRange(it, range) } } else { records.map { Range(it.timeStarted, it.timeEnded) } } diff --git a/features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/interactor/StatisticsDetailStatsInteractor.kt b/features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/interactor/StatisticsDetailStatsInteractor.kt index 9209f34c..b845f3c9 100644 --- a/features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/interactor/StatisticsDetailStatsInteractor.kt +++ b/features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/interactor/StatisticsDetailStatsInteractor.kt @@ -2,7 +2,6 @@ package com.example.util.simpletimetracker.feature_statistics_detail.interactor import com.example.util.simpletimetracker.core.mapper.ColorMapper import com.example.util.simpletimetracker.core.mapper.IconMapper -import com.example.util.simpletimetracker.domain.mapper.RangeMapper import com.example.util.simpletimetracker.core.mapper.TimeMapper import com.example.util.simpletimetracker.core.repo.ResourceRepo import com.example.util.simpletimetracker.domain.UNCATEGORIZED_ITEM_ID @@ -10,10 +9,10 @@ import com.example.util.simpletimetracker.domain.extension.orZero import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor import com.example.util.simpletimetracker.domain.interactor.RecordTagInteractor import com.example.util.simpletimetracker.domain.interactor.RecordTypeInteractor +import com.example.util.simpletimetracker.domain.mapper.RangeMapper import com.example.util.simpletimetracker.domain.mapper.StatisticsMapper -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.RecordBase import com.example.util.simpletimetracker.domain.model.RecordTag import com.example.util.simpletimetracker.domain.model.RecordType import com.example.util.simpletimetracker.feature_base_adapter.ViewHolderType @@ -40,8 +39,8 @@ class StatisticsDetailStatsInteractor @Inject constructor( ) { suspend fun getStatsViewData( - records: List, - compareRecords: List, + records: List, + compareRecords: List, showComparison: Boolean, rangeLength: RangeLength, rangePosition: Int, @@ -60,9 +59,7 @@ class StatisticsDetailStatsInteractor @Inject constructor( shift = rangePosition, firstDayOfWeek = firstDayOfWeek, startOfDayShift = startOfDayShift - ).let { - Range(it.first, it.second) - } + ) return@withContext mapStatsData( records = if (range.timeStarted == 0L && range.timeEnded == 0L) { @@ -109,8 +106,8 @@ class StatisticsDetailStatsInteractor @Inject constructor( } private fun mapStatsData( - records: List, - compareRecords: List, + records: List, + compareRecords: List, showComparison: Boolean, types: List, tags: List, @@ -120,10 +117,10 @@ class StatisticsDetailStatsInteractor @Inject constructor( showSeconds: Boolean, ): StatisticsDetailStatsViewData { val recordsSorted = records.sortedBy { it.timeStarted } - val durations = records.map(::mapToDuration) + val durations = records.map(RecordBase::duration) val compareRecordsSorted = compareRecords.sortedBy { it.timeStarted } - val compareDurations = compareRecords.map(::mapToDuration) + val compareDurations = compareRecords.map(RecordBase::duration) val emptyValue by lazy { resourceRepo.getString(R.string.statistics_detail_empty) @@ -298,18 +295,14 @@ class StatisticsDetailStatsInteractor @Inject constructor( ) } - private fun mapToDuration(record: Record): Long { - return record.let { it.timeEnded - it.timeStarted } - } - private fun mapActivities( - records: List, + records: List, typesMap: Map, isDarkTheme: Boolean, useProportionalMinutes: Boolean, showSeconds: Boolean, ): List { - val activities: MutableMap> = mutableMapOf() + val activities: MutableMap> = mutableMapOf() records.forEach { record -> activities.getOrPut(record.typeId) { mutableListOf() }.add(record) @@ -348,14 +341,14 @@ class StatisticsDetailStatsInteractor @Inject constructor( } private fun mapTags( - records: List, + records: List, typesMap: Map, tagsMap: Map, isDarkTheme: Boolean, useProportionalMinutes: Boolean, showSeconds: Boolean, ): List { - val tags: MutableMap> = mutableMapOf() + val tags: MutableMap> = mutableMapOf() records.forEach { record -> record.tagIds.forEach { tagId -> diff --git a/features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/interactor/StatisticsDetailStreaksInteractor.kt b/features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/interactor/StatisticsDetailStreaksInteractor.kt index c835f528..ebeeb706 100644 --- a/features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/interactor/StatisticsDetailStreaksInteractor.kt +++ b/features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/interactor/StatisticsDetailStreaksInteractor.kt @@ -1,15 +1,15 @@ package com.example.util.simpletimetracker.feature_statistics_detail.interactor import com.example.util.simpletimetracker.core.extension.setToStartOfDay -import com.example.util.simpletimetracker.domain.mapper.RangeMapper import com.example.util.simpletimetracker.core.mapper.TimeMapper import com.example.util.simpletimetracker.core.repo.ResourceRepo import com.example.util.simpletimetracker.domain.extension.orZero import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor +import com.example.util.simpletimetracker.domain.mapper.RangeMapper import com.example.util.simpletimetracker.domain.model.DayOfWeek 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.RecordBase import com.example.util.simpletimetracker.feature_base_adapter.ViewHolderType import com.example.util.simpletimetracker.feature_statistics_detail.R import com.example.util.simpletimetracker.feature_statistics_detail.customView.SeriesView @@ -48,8 +48,8 @@ class StatisticsDetailStreaksInteractor @Inject constructor( } suspend fun getStreaksViewData( - records: List, - compareRecords: List, + records: List, + compareRecords: List, showComparison: Boolean, rangeLength: RangeLength, rangePosition: Int, @@ -63,9 +63,7 @@ class StatisticsDetailStreaksInteractor @Inject constructor( shift = rangePosition, firstDayOfWeek = firstDayOfWeek, startOfDayShift = startOfDayShift - ).let { - Range(timeStarted = it.first, timeEnded = it.second) - } + ) val (maxStreak, currentStreak, data) = mapStatsData( range = range, @@ -149,7 +147,7 @@ class StatisticsDetailStreaksInteractor @Inject constructor( private fun mapStatsData( range: Range, - records: List, + records: List, rangeLength: RangeLength, firstDayOfWeek: DayOfWeek, startOfDayShift: Long, @@ -180,7 +178,7 @@ class StatisticsDetailStreaksInteractor @Inject constructor( private fun calculate( range: Range, - records: List, + records: List, firstDayOfWeek: DayOfWeek, startOfDayShift: Long, streaksType: StreaksType, @@ -203,8 +201,10 @@ class StatisticsDetailStreaksInteractor @Inject constructor( ).map { rangeMapper.clampToRange( record = it, - rangeStart = day.timeStarted, - rangeEnd = day.timeEnded, + range = Range( + timeStarted = day.timeStarted, + timeEnded = day.timeEnded, + ) ) }.sumOf { it.duration diff --git a/features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/viewModel/StatisticsDetailViewModel.kt b/features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/viewModel/StatisticsDetailViewModel.kt index 471dc784..46c05d5b 100644 --- a/features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/viewModel/StatisticsDetailViewModel.kt +++ b/features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/viewModel/StatisticsDetailViewModel.kt @@ -19,7 +19,7 @@ import com.example.util.simpletimetracker.core.viewData.SelectRangeViewData import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor 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.RecordBase import com.example.util.simpletimetracker.domain.model.RecordsFilter import com.example.util.simpletimetracker.feature_base_adapter.ViewHolderType import com.example.util.simpletimetracker.feature_statistics_detail.R @@ -136,8 +136,8 @@ class StatisticsDetailViewModel @Inject constructor( extra.filter.map(RecordsFilterParam::toModel).toMutableList() } private val comparisonFilter: MutableList = mutableListOf() - private var records: List = emptyList() // all records with selected ids - private var compareRecords: List = emptyList() // all records with selected ids + private var records: List = emptyList() // all records with selected ids + private var compareRecords: List = emptyList() // all records with selected ids private var loadJob: Job? = null fun initialize(extra: StatisticsDetailParams) { diff --git a/features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/statistics/settings/WidgetStatisticsSettingsViewModel.kt b/features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/statistics/settings/WidgetStatisticsSettingsViewModel.kt index 5841b8ad..fc6ff53e 100644 --- a/features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/statistics/settings/WidgetStatisticsSettingsViewModel.kt +++ b/features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/statistics/settings/WidgetStatisticsSettingsViewModel.kt @@ -8,7 +8,6 @@ import com.example.util.simpletimetracker.core.extension.addOrRemove import com.example.util.simpletimetracker.core.extension.set import com.example.util.simpletimetracker.core.interactor.ChartFilterViewDataInteractor import com.example.util.simpletimetracker.core.mapper.ChartFilterViewDataMapper -import com.example.util.simpletimetracker.domain.mapper.RangeMapper import com.example.util.simpletimetracker.core.mapper.RangeViewDataMapper import com.example.util.simpletimetracker.core.view.buttonsRowView.ButtonsRowViewData import com.example.util.simpletimetracker.core.viewData.ChartFilterTypeViewData diff --git a/navigation/src/main/java/com/example/util/simpletimetracker/navigation/params/screen/ChangeRunningRecordFromMainParams.kt b/navigation/src/main/java/com/example/util/simpletimetracker/navigation/params/screen/ChangeRunningRecordFromMainParams.kt new file mode 100644 index 00000000..c0472a7c --- /dev/null +++ b/navigation/src/main/java/com/example/util/simpletimetracker/navigation/params/screen/ChangeRunningRecordFromMainParams.kt @@ -0,0 +1,5 @@ +package com.example.util.simpletimetracker.navigation.params.screen + +data class ChangeRunningRecordFromMainParams( + override val params: ChangeRunningRecordParams, +) : ChangeRunningRecordFromScreen \ No newline at end of file diff --git a/navigation/src/main/java/com/example/util/simpletimetracker/navigation/params/screen/ChangeRunningRecordFromRecordsAllParams.kt b/navigation/src/main/java/com/example/util/simpletimetracker/navigation/params/screen/ChangeRunningRecordFromRecordsAllParams.kt new file mode 100644 index 00000000..0d0adc55 --- /dev/null +++ b/navigation/src/main/java/com/example/util/simpletimetracker/navigation/params/screen/ChangeRunningRecordFromRecordsAllParams.kt @@ -0,0 +1,5 @@ +package com.example.util.simpletimetracker.navigation.params.screen + +data class ChangeRunningRecordFromRecordsAllParams( + override val params: ChangeRunningRecordParams, +) : ChangeRunningRecordFromScreen \ No newline at end of file diff --git a/navigation/src/main/java/com/example/util/simpletimetracker/navigation/params/screen/ChangeRunningRecordFromScreen.kt b/navigation/src/main/java/com/example/util/simpletimetracker/navigation/params/screen/ChangeRunningRecordFromScreen.kt new file mode 100644 index 00000000..608cc4f7 --- /dev/null +++ b/navigation/src/main/java/com/example/util/simpletimetracker/navigation/params/screen/ChangeRunningRecordFromScreen.kt @@ -0,0 +1,6 @@ +package com.example.util.simpletimetracker.navigation.params.screen + +interface ChangeRunningRecordFromScreen : ScreenParams { + + val params: ChangeRunningRecordParams +} \ No newline at end of file diff --git a/navigation/src/main/java/com/example/util/simpletimetracker/navigation/params/screen/RecordsFilterParams.kt b/navigation/src/main/java/com/example/util/simpletimetracker/navigation/params/screen/RecordsFilterParams.kt index 42b44dc6..06f972e8 100644 --- a/navigation/src/main/java/com/example/util/simpletimetracker/navigation/params/screen/RecordsFilterParams.kt +++ b/navigation/src/main/java/com/example/util/simpletimetracker/navigation/params/screen/RecordsFilterParams.kt @@ -9,5 +9,6 @@ data class RecordsFilterParams( val title: String = "", val dateSelectionAvailable: Boolean = true, val untrackedSelectionAvailable: Boolean = true, + val addRunningRecords: Boolean = true, val filters: List = emptyList(), ) : ScreenParams, Parcelable \ No newline at end of file