Skip to content

Commit a4d17c1

Browse files
committed
add clickable stat detail previews
1 parent f80489c commit a4d17c1

22 files changed

Lines changed: 277 additions & 108 deletions

File tree

core/src/main/java/com/example/util/simpletimetracker/core/interactor/GetTotalStatisticsFilterInteractor.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class GetTotalStatisticsFilterInteractor @Inject constructor(
1818
) {
1919

2020
suspend fun execute(
21-
filterType: ChartFilterType
21+
filterType: ChartFilterType,
2222
): RecordsFilter {
2323
return when (filterType) {
2424
ChartFilterType.ACTIVITY -> {

domain/src/test/java/com/example/util/simpletimetracker/domain/mapper/AddRunningRecordMediatorTest.kt

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -632,26 +632,6 @@ class AddRunningRecordMediatorTest {
632632
// Given
633633
`when`(prefsInteractor.getRetroactiveTrackingMode()).thenReturn(true)
634634
`when`(recordInteractor.getAllPrev(any())).thenReturn(emptyList())
635-
// `when`(recordInteractor.getAllPrev(any())).thenReturn(
636-
// listOf(
637-
// Record(
638-
// id = 0L,
639-
// typeId = typeId2,
640-
// timeStarted = 0,
641-
// timeEnded = 0,
642-
// comment = "",
643-
// tags = emptyList(),
644-
// ),
645-
// Record(
646-
// id = 0L,
647-
// typeId = typeId3,
648-
// timeStarted = 0,
649-
// timeEnded = 0,
650-
// comment = "",
651-
// tags = emptyList(),
652-
// ),
653-
// ),
654-
// )
655635

656636
// When
657637
subject.startTimer(
@@ -725,7 +705,7 @@ class AddRunningRecordMediatorTest {
725705
}
726706

727707
@Test
728-
fun retroactiveMerge(): Unit = runBlocking {
708+
fun retroactiveNoMerge(): Unit = runBlocking {
729709
// Given
730710
`when`(prefsInteractor.getRetroactiveTrackingMode()).thenReturn(true)
731711
`when`(recordInteractor.getAllPrev(any())).thenReturn(
@@ -756,9 +736,9 @@ class AddRunningRecordMediatorTest {
756736
verify(addRecordMediator).add(
757737
record = eq(
758738
Record(
759-
id = 10L,
739+
id = 0L,
760740
typeId = typeId,
761-
timeStarted = 1000,
741+
timeStarted = 2000,
762742
timeEnded = currentTime,
763743
comment = "comment2",
764744
tags = listOf(tag(tagId2)),

features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/interactor/RecordsFilterExcludeInteractorImpl.kt

Lines changed: 7 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,6 @@ package com.example.util.simpletimetracker.feature_records_filter.interactor
33
import com.example.util.simpletimetracker.domain.base.UNCATEGORIZED_ITEM_ID
44
import com.example.util.simpletimetracker.domain.base.UNTRACKED_ITEM_ID
55
import com.example.util.simpletimetracker.domain.category.interactor.RecordTypeCategoryInteractor
6-
import com.example.util.simpletimetracker.domain.record.extension.getCategoryItems
7-
import com.example.util.simpletimetracker.domain.record.extension.getSelectedTags
8-
import com.example.util.simpletimetracker.domain.record.extension.getTypeIds
9-
import com.example.util.simpletimetracker.domain.record.extension.hasSelectedActivityFilter
10-
import com.example.util.simpletimetracker.domain.record.extension.hasSelectedCategoryFilter
11-
import com.example.util.simpletimetracker.domain.record.extension.hasSelectedTagsFilter
126
import com.example.util.simpletimetracker.domain.record.model.RecordsFilter
137
import com.example.util.simpletimetracker.domain.recordTag.interactor.RecordTagInteractor
148
import com.example.util.simpletimetracker.domain.recordTag.interactor.RecordTypeToTagInteractor
@@ -36,15 +30,10 @@ class RecordsFilterExcludeInteractorImpl @Inject constructor(
3630

3731
return when (type) {
3832
is ExcludeType.Activity -> {
39-
val itemIsSelected = currentFilters.hasSelectedActivityFilter() &&
40-
id in currentFilters.getTypeIds()
4133
recordsFilterUpdateInteractor.handleTypeClick(
42-
type = if (itemIsSelected) {
43-
RecordFilterSelectionType.Select
44-
} else {
45-
RecordFilterSelectionType.Filter
46-
},
34+
type = RecordFilterSelectionType.Filter,
4735
id = id,
36+
allowSameIdInSelectedFiltered = true,
4837
currentFilters = currentFilters,
4938
recordTypes = recordTypeInteractor.getAll(),
5039
recordTypeCategories = recordTypeCategoryInteractor.getAll(),
@@ -53,20 +42,10 @@ class RecordsFilterExcludeInteractorImpl @Inject constructor(
5342
)
5443
}
5544
is ExcludeType.Category -> {
56-
val item = if (id == UNCATEGORIZED_ITEM_ID) {
57-
RecordsFilter.CategoryItem.Uncategorized
58-
} else {
59-
RecordsFilter.CategoryItem.Categorized(id)
60-
}
61-
val itemIsSelected = currentFilters.hasSelectedCategoryFilter() &&
62-
item in currentFilters.getCategoryItems()
6345
recordsFilterUpdateInteractor.handleCategoryClick(
64-
type = if (itemIsSelected) {
65-
RecordFilterSelectionType.Select
66-
} else {
67-
RecordFilterSelectionType.Filter
68-
},
46+
type = RecordFilterSelectionType.Filter,
6947
id = id,
48+
allowSameIdInSelectedFiltered = true,
7049
currentFilters = currentFilters,
7150
recordTypes = recordTypeInteractor.getAll(),
7251
recordTypeCategories = recordTypeCategoryInteractor.getAll(),
@@ -75,21 +54,11 @@ class RecordsFilterExcludeInteractorImpl @Inject constructor(
7554
)
7655
}
7756
is ExcludeType.Tag -> {
78-
val item = if (id == UNCATEGORIZED_ITEM_ID) {
79-
RecordsFilter.TagItem.Untagged
80-
} else {
81-
RecordsFilter.TagItem.Tagged(id)
82-
}
83-
val itemIsSelected = currentFilters.hasSelectedTagsFilter() &&
84-
item in currentFilters.getSelectedTags()
8557
recordsFilterUpdateInteractor.handleTagClick(
86-
type = if (itemIsSelected) {
87-
RecordFilterSelectionType.Select
88-
} else {
89-
RecordFilterSelectionType.Filter
90-
},
58+
type = RecordFilterSelectionType.Filter,
9159
currentFilters = currentFilters,
9260
itemId = id,
61+
allowSameIdInSelectedFiltered = true,
9362
)
9463
}
9564
}
@@ -99,6 +68,7 @@ class RecordsFilterExcludeInteractorImpl @Inject constructor(
9968
id: Long,
10069
type: ExcludeType,
10170
): List<RecordsFilter> {
71+
// Shouldn't be possible
10272
if (id == UNTRACKED_ITEM_ID) return listOf(RecordsFilter.Untracked)
10373

10474
return when (type) {

features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/interactor/RecordsFilterUpdateInteractor.kt

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class RecordsFilterUpdateInteractor @Inject constructor(
5656
fun handleTypeClick(
5757
type: RecordFilterSelectionType,
5858
id: Long,
59+
allowSameIdInSelectedFiltered: Boolean,
5960
currentFilters: List<RecordsFilter>,
6061
recordTypes: List<RecordType>,
6162
recordTypeCategories: List<RecordTypeCategory>,
@@ -85,6 +86,7 @@ class RecordsFilterUpdateInteractor @Inject constructor(
8586
type = type,
8687
currentFilters = filters,
8788
newIds = newIds,
89+
allowSameIdInSelectedFiltered = allowSameIdInSelectedFiltered,
8890
).let {
8991
checkTagFilterConsistency(
9092
currentFilters = it,
@@ -99,6 +101,7 @@ class RecordsFilterUpdateInteractor @Inject constructor(
99101
fun handleCategoryClick(
100102
type: RecordFilterSelectionType,
101103
id: Long,
104+
allowSameIdInSelectedFiltered: Boolean,
102105
currentFilters: List<RecordsFilter>,
103106
recordTypes: List<RecordType>,
104107
recordTypeCategories: List<RecordTypeCategory>,
@@ -120,6 +123,7 @@ class RecordsFilterUpdateInteractor @Inject constructor(
120123
type = type,
121124
currentFilters = filters,
122125
newItems = newItems,
126+
allowSameIdInSelectedFiltered = allowSameIdInSelectedFiltered,
123127
).let {
124128
checkTagFilterConsistency(
125129
currentFilters = it,
@@ -135,6 +139,7 @@ class RecordsFilterUpdateInteractor @Inject constructor(
135139
type: RecordFilterSelectionType,
136140
currentFilters: List<RecordsFilter>,
137141
itemId: Long,
142+
allowSameIdInSelectedFiltered: Boolean,
138143
): List<RecordsFilter> {
139144
val filters = currentFilters.toMutableList()
140145
val currentTags = when (type) {
@@ -151,6 +156,7 @@ class RecordsFilterUpdateInteractor @Inject constructor(
151156
type = type,
152157
currentFilters = filters,
153158
newItems = newTags,
159+
allowSameIdInSelectedFiltered = allowSameIdInSelectedFiltered,
154160
)
155161
}
156162

@@ -438,6 +444,7 @@ class RecordsFilterUpdateInteractor @Inject constructor(
438444
type = type,
439445
currentFilters = currentFilters,
440446
newIds = newIds,
447+
allowSameIdInSelectedFiltered = false,
441448
).let {
442449
checkTagFilterConsistency(
443450
currentFilters = it,
@@ -473,6 +480,7 @@ class RecordsFilterUpdateInteractor @Inject constructor(
473480
type = type,
474481
currentFilters = currentFilters,
475482
newItems = newItems,
483+
allowSameIdInSelectedFiltered = false,
476484
).let {
477485
checkTagFilterConsistency(
478486
currentFilters = it,
@@ -504,6 +512,7 @@ class RecordsFilterUpdateInteractor @Inject constructor(
504512
type = type,
505513
currentFilters = currentFilters,
506514
newItems = newItems,
515+
allowSameIdInSelectedFiltered = false,
507516
)
508517
}
509518

@@ -555,16 +564,21 @@ class RecordsFilterUpdateInteractor @Inject constructor(
555564
type: RecordFilterSelectionType,
556565
currentFilters: List<RecordsFilter>,
557566
newIds: List<Long>,
567+
allowSameIdInSelectedFiltered: Boolean,
558568
): List<RecordsFilter> {
559569
val filters = currentFilters.toMutableList()
560570

561571
val newFilter = when (type) {
562572
is RecordFilterSelectionType.Select -> RecordsFilter.Activity(
563573
selected = newIds,
564-
filtered = filters.getFilteredTypeIds().filter { it !in newIds },
574+
filtered = filters.getFilteredTypeIds().filter {
575+
if (!allowSameIdInSelectedFiltered) it !in newIds else true
576+
},
565577
)
566578
is RecordFilterSelectionType.Filter -> RecordsFilter.Activity(
567-
selected = filters.getTypeIds().filter { it !in newIds },
579+
selected = filters.getTypeIds().filter {
580+
if (!allowSameIdInSelectedFiltered) it !in newIds else true
581+
},
568582
filtered = newIds,
569583
)
570584
}
@@ -590,16 +604,21 @@ class RecordsFilterUpdateInteractor @Inject constructor(
590604
type: RecordFilterSelectionType,
591605
currentFilters: List<RecordsFilter>,
592606
newItems: List<RecordsFilter.CategoryItem>,
607+
allowSameIdInSelectedFiltered: Boolean,
593608
): List<RecordsFilter> {
594609
val filters = currentFilters.toMutableList()
595610

596611
val newFilter = when (type) {
597612
is RecordFilterSelectionType.Select -> RecordsFilter.Category(
598613
selected = newItems,
599-
filtered = filters.getFilteredCategoryItems().filter { it !in newItems },
614+
filtered = filters.getFilteredCategoryItems().filter {
615+
if (!allowSameIdInSelectedFiltered) it !in newItems else true
616+
},
600617
)
601618
is RecordFilterSelectionType.Filter -> RecordsFilter.Category(
602-
selected = filters.getCategoryItems().filter { it !in newItems },
619+
selected = filters.getCategoryItems().filter {
620+
if (!allowSameIdInSelectedFiltered) it !in newItems else true
621+
},
603622
filtered = newItems,
604623
)
605624
}
@@ -625,16 +644,21 @@ class RecordsFilterUpdateInteractor @Inject constructor(
625644
type: RecordFilterSelectionType,
626645
currentFilters: List<RecordsFilter>,
627646
newItems: List<RecordsFilter.TagItem>,
647+
allowSameIdInSelectedFiltered: Boolean,
628648
): List<RecordsFilter> {
629649
val filters = currentFilters.toMutableList()
630650

631651
val newFilter = when (type) {
632652
RecordFilterSelectionType.Select -> RecordsFilter.Tags(
633653
selected = newItems,
634-
filtered = filters.getFilteredTags().filter { it !in newItems },
654+
filtered = filters.getFilteredTags().filter {
655+
if (!allowSameIdInSelectedFiltered) it !in newItems else true
656+
},
635657
)
636658
RecordFilterSelectionType.Filter -> RecordsFilter.Tags(
637-
selected = filters.getSelectedTags().filter { it !in newItems },
659+
selected = filters.getSelectedTags().filter {
660+
if (!allowSameIdInSelectedFiltered) it !in newItems else true
661+
},
638662
filtered = newItems,
639663
)
640664
}

features/feature_records_filter/src/main/java/com/example/util/simpletimetracker/feature_records_filter/viewModel/RecordsFilterViewModel.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ class RecordsFilterViewModel @Inject constructor(
388388
filters = recordsFilterUpdateInteractor.handleTypeClick(
389389
type = type,
390390
id = id,
391+
allowSameIdInSelectedFiltered = false,
391392
currentFilters = filters,
392393
recordTypes = getTypesCache(),
393394
recordTypeCategories = getRecordTypeCategoriesCache(),
@@ -405,6 +406,7 @@ class RecordsFilterViewModel @Inject constructor(
405406
RecordFilterSelectionType.Select
406407
},
407408
id = item.id,
409+
allowSameIdInSelectedFiltered = false,
408410
currentFilters = filters,
409411
recordTypes = getTypesCache(),
410412
recordTypeCategories = getRecordTypeCategoriesCache(),
@@ -472,6 +474,7 @@ class RecordsFilterViewModel @Inject constructor(
472474
type = tagSelectionState,
473475
currentFilters = filters,
474476
itemId = item.id,
477+
allowSameIdInSelectedFiltered = false,
475478
)
476479
}
477480

features/feature_statistics/src/main/java/com/example/util/simpletimetracker/feature_statistics/mapper/StatisticsViewDataMapper.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class StatisticsViewDataMapper @Inject constructor(
2424
isDarkTheme: Boolean,
2525
): ViewHolderType {
2626
val id = "statistics_total_tracked".hashCode().toLong()
27-
val transitionName = "${TransitionNames.STATISTICS_DETAIL}_shift${shift}_id${id}"
27+
val transitionName = "${TransitionNames.STATISTICS_DETAIL}_shift${shift}_id$id"
2828
val data = StatisticsViewData(
2929
id = id,
3030
name = resourceRepo.getString(R.string.statistics_total_tracked),
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,33 @@
11
package com.example.util.simpletimetracker.feature_statistics_detail.adapter
22

33
import com.example.util.simpletimetracker.feature_base_adapter.createRecyclerBindingAdapterDelegate
4+
import com.example.util.simpletimetracker.feature_statistics_detail.viewData.StatisticsDetailPreview
5+
import com.example.util.simpletimetracker.feature_views.extension.setOnClickWith
6+
import com.example.util.simpletimetracker.feature_views.extension.setOnLongClickWith
47
import com.example.util.simpletimetracker.feature_views.extension.visible
58
import com.example.util.simpletimetracker.feature_statistics_detail.databinding.StatisticsDetailPreviewItemBinding as Binding
69
import com.example.util.simpletimetracker.feature_statistics_detail.viewData.StatisticsDetailPreviewViewData as ViewData
710

8-
fun createStatisticsPreviewAdapterDelegate() =
9-
createRecyclerBindingAdapterDelegate<ViewData, Binding>(
10-
Binding::inflate,
11-
) { binding, item, _ ->
11+
fun createStatisticsPreviewAdapterDelegate(
12+
onClick: ((StatisticsDetailPreview) -> Unit)? = null,
13+
onLongClick: ((StatisticsDetailPreview) -> Unit)? = null,
14+
) = createRecyclerBindingAdapterDelegate<ViewData, Binding>(
15+
Binding::inflate,
16+
) { binding, item, _ ->
1217

13-
with(binding) {
14-
item as ViewData
18+
with(binding) {
19+
item as ViewData
1520

16-
layoutStatisticsDetailPreviewItem.setCardBackgroundColor(item.color)
17-
tvStatisticsDetailPreviewItemName.visible = item.name.isNotEmpty()
18-
item.name.takeIf { it.isNotEmpty() }
19-
?.let(tvStatisticsDetailPreviewItemName::setText)
20-
ivStatisticsDetailPreviewItemIcon.visible = item.iconId != null
21-
item.iconId?.let(ivStatisticsDetailPreviewItemIcon::itemIcon::set)
22-
}
23-
}
21+
layoutStatisticsDetailPreviewItem.setCardBackgroundColor(item.color)
22+
tvStatisticsDetailPreviewItemName.visible = item.name.isNotEmpty()
23+
item.name.takeIf { it.isNotEmpty() }
24+
?.let(tvStatisticsDetailPreviewItemName::setText)
25+
ivStatisticsDetailPreviewItemIcon.visible = item.iconId != null
26+
item.iconId?.let(ivStatisticsDetailPreviewItemIcon::itemIcon::set)
27+
item.iconColor?.let(ivStatisticsDetailPreviewItemIcon::itemIconColor::set)
28+
ivStatisticsDetailPreviewItemIcon.itemIconAlpha = item.iconAlpha
29+
30+
onClick?.let { root.setOnClickWith(item, it) }
31+
onLongClick?.let { root.setOnLongClickWith(item, it) }
32+
}
33+
}

features/feature_statistics_detail/src/main/java/com/example/util/simpletimetracker/feature_statistics_detail/adapter/StatisticsDetailPreviewsAdapterDelegate.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,17 @@ import com.example.util.simpletimetracker.feature_statistics_detail.databinding.
88

99
fun createStatisticsDetailPreviewsAdapterDelegate(
1010
onClick: (StatisticsDetailPreview) -> Unit,
11+
onLongClick: (StatisticsDetailPreview) -> Unit,
1112
) = createRecyclerBindingAdapterDelegate<ViewData, Binding>(
1213
Binding::inflate,
1314
) { binding, item, _ ->
1415

1516
with(binding) {
1617
item as ViewData
1718

18-
root.adapter.replaceFast(item.data)
19+
root.adapter.replace(item.data)
1920
root.setClickListener(onClick)
21+
root.setLongClickListener(onLongClick)
2022
}
2123
}
2224

0 commit comments

Comments
 (0)