Skip to content

Commit fbbe634

Browse files
committed
refactor tag selection view data
1 parent 5e3f091 commit fbbe634

7 files changed

Lines changed: 134 additions & 107 deletions

File tree

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

Lines changed: 118 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.example.util.simpletimetracker.core.R
44
import com.example.util.simpletimetracker.core.mapper.CategoryViewDataMapper
55
import com.example.util.simpletimetracker.core.mapper.CommonViewDataMapper
66
import com.example.util.simpletimetracker.core.repo.ResourceRepo
7+
import com.example.util.simpletimetracker.domain.extension.addBetweenEach
78
import com.example.util.simpletimetracker.domain.extension.plusAssign
89
import com.example.util.simpletimetracker.domain.prefs.interactor.PrefsInteractor
910
import com.example.util.simpletimetracker.domain.record.model.RecordBase
@@ -34,6 +35,7 @@ class RecordTagViewDataInteractor @Inject constructor(
3435
showAllTags: Boolean,
3536
multipleChoiceAvailable: Boolean,
3637
showAddButton: Boolean,
38+
showHint: Boolean,
3739
showArchived: Boolean,
3840
showUntaggedButton: Boolean,
3941
showAllTagsButton: Boolean,
@@ -44,135 +46,149 @@ class RecordTagViewDataInteractor @Inject constructor(
4446

4547
val isDarkTheme = prefsInteractor.getDarkMode()
4648
val allTags = recordTagInteractor.getAll().filterArchived()
49+
50+
if (allTags.isEmpty()) {
51+
return mapEmpty(
52+
showAddButton = showAddButton,
53+
isDarkTheme = isDarkTheme,
54+
)
55+
}
56+
4757
val recordTags = getSelectableTagsInteractor.execute(*typeIds.toLongArray()).filterArchived()
4858
val recordTagIds = recordTags.map { it.id }
4959
val tagsFromOtherActivities = allTags.filter { it.id !in recordTagIds }
5060
val hasMoreTags = tagsFromOtherActivities.isNotEmpty()
5161
val types = recordTypeInteractor.getAll().associateBy { it.id }
5262

53-
return if (allTags.isNotEmpty()) {
54-
val selectedTagsMap = selectedTags.associateBy { it.tagId }
55-
val selectedTagIds = selectedTagsMap.keys
56-
val selected = allTags.filter { it.id in selectedTagIds }
57-
val available = recordTags.filter { it.id !in selectedTagIds }
58-
val availableFromOtherActivities = if (showAllTags) {
59-
tagsFromOtherActivities.filter { it.id !in selectedTagIds }
60-
} else {
61-
emptyList()
62-
}
63+
val selectedTagsMap = selectedTags.associateBy { it.tagId }
64+
val selectedTagIds = selectedTagsMap.keys
65+
val selected = allTags.filter { it.id in selectedTagIds }
66+
val available = recordTags.filter { it.id !in selectedTagIds }
67+
val availableFromOtherActivities = if (showAllTags) {
68+
tagsFromOtherActivities.filter { it.id !in selectedTagIds }
69+
} else {
70+
emptyList()
71+
}
6372

64-
val viewData = mutableListOf<ViewHolderType>()
65-
val buttonsViewData = mutableListOf<ViewHolderType>()
73+
// Hint
74+
val hintViewData = if (showHint) {
75+
listOf(categoryViewDataMapper.mapToRecordTagHint())
76+
} else {
77+
emptyList()
78+
}
6679

67-
if (showAddButton) {
68-
viewData += listOf(
69-
categoryViewDataMapper.mapToRecordTagHint(),
70-
DividerViewData("divider_hint".hashCode().toLong()),
71-
)
72-
}
80+
// Selected
81+
val selectedViewData = mutableListOf<ViewHolderType>()
82+
if (multipleChoiceAvailable) {
83+
selectedViewData += commonViewDataMapper.mapSelectedHint(
84+
isEmpty = selected.isEmpty(),
85+
)
86+
} else if (selected.isNotEmpty()) {
87+
selectedViewData += InfoViewData(
88+
text = resourceRepo.getString(R.string.something_preselected),
89+
)
90+
}
91+
selectedViewData += selected.map {
92+
categoryViewDataMapper.mapRecordTagWithValue(
93+
tag = it,
94+
tagData = selectedTagsMap[it.id],
95+
types = types,
96+
isDarkTheme = isDarkTheme,
97+
)
98+
}
7399

74-
if (multipleChoiceAvailable) {
75-
viewData += commonViewDataMapper.mapSelectedHint(
76-
isEmpty = selected.isEmpty(),
77-
)
78-
} else if (selected.isNotEmpty()) {
79-
viewData += InfoViewData(
80-
text = resourceRepo.getString(R.string.something_preselected),
81-
)
100+
// Available
101+
val availableViewData = mutableListOf<ViewHolderType>()
102+
categoryViewDataMapper.groupToTagGroups(available).forEach { (groupName, tags) ->
103+
if (groupName.isNotEmpty()) {
104+
availableViewData += InfoViewData(text = groupName)
82105
}
83106

84-
viewData += selected.map {
85-
categoryViewDataMapper.mapRecordTagWithValue(
107+
availableViewData += tags.map {
108+
categoryViewDataMapper.mapRecordTag(
86109
tag = it,
87-
tagData = selectedTagsMap[it.id],
88110
types = types,
89111
isDarkTheme = isDarkTheme,
90112
)
91113
}
114+
}
92115

93-
if (
94-
(multipleChoiceAvailable && available.isNotEmpty()) ||
95-
(!multipleChoiceAvailable && selected.isNotEmpty() && available.isNotEmpty())
96-
) {
97-
viewData += DividerViewData("divider_available".hashCode().toLong())
98-
}
99-
100-
categoryViewDataMapper.groupToTagGroups(available).forEach { (groupName, tags) ->
101-
if (groupName.isNotEmpty()) {
102-
viewData += InfoViewData(text = groupName)
103-
}
104-
105-
viewData += tags.map {
106-
categoryViewDataMapper.mapRecordTag(
107-
tag = it,
108-
types = types,
109-
isDarkTheme = isDarkTheme,
110-
)
111-
}
112-
}
113-
114-
if (availableFromOtherActivities.isNotEmpty()) {
115-
viewData += DividerViewData("divider_from_other".hashCode().toLong())
116-
117-
viewData += HintViewData(
118-
text = resourceRepo.getString(R.string.change_record_tag_from_other_activity),
119-
)
120-
121-
viewData += availableFromOtherActivities.map {
122-
categoryViewDataMapper.mapRecordTag(
123-
tag = it,
124-
types = types,
125-
isDarkTheme = isDarkTheme,
126-
)
127-
}
128-
}
129-
130-
if (showUntaggedButton) {
131-
buttonsViewData += categoryViewDataMapper.mapToUntaggedItem(
132-
isDarkTheme = isDarkTheme,
133-
isFiltered = false,
134-
)
135-
}
116+
// From other
117+
val availableFromOtherViewData = mutableListOf<ViewHolderType>()
118+
if (availableFromOtherActivities.isNotEmpty()) {
119+
availableFromOtherViewData += HintViewData(
120+
text = resourceRepo.getString(R.string.change_record_tag_from_other_activity),
121+
)
136122

137-
if (showAllTagsButton && !showAllTags && hasMoreTags) {
138-
buttonsViewData += categoryViewDataMapper.mapToRecordTagShowAllItem(
123+
availableFromOtherViewData += availableFromOtherActivities.map {
124+
categoryViewDataMapper.mapRecordTag(
125+
tag = it,
126+
types = types,
139127
isDarkTheme = isDarkTheme,
140128
)
141129
}
130+
}
142131

143-
if (showAddButton) {
144-
buttonsViewData += categoryViewDataMapper.mapToRecordTagAddItem(isDarkTheme)
145-
}
132+
// Buttons
133+
val buttonsViewData = mutableListOf<ViewHolderType>()
134+
if (showUntaggedButton) {
135+
buttonsViewData += categoryViewDataMapper.mapToUntaggedItem(
136+
isDarkTheme = isDarkTheme,
137+
isFiltered = false,
138+
)
139+
}
140+
if (showAllTagsButton && !showAllTags && hasMoreTags) {
141+
buttonsViewData += categoryViewDataMapper.mapToRecordTagShowAllItem(
142+
isDarkTheme = isDarkTheme,
143+
)
144+
}
145+
if (showAddButton) {
146+
buttonsViewData += categoryViewDataMapper.mapToRecordTagAddItem(isDarkTheme)
147+
}
146148

147-
if (buttonsViewData.isNotEmpty()) {
148-
if (multipleChoiceAvailable ||
149-
selected.isNotEmpty() ||
150-
availableFromOtherActivities.isNotEmpty()
151-
) {
152-
viewData += DividerViewData("divider_buttons".hashCode().toLong())
149+
// All
150+
val viewData = listOf(
151+
hintViewData to true,
152+
selectedViewData to true,
153+
availableViewData to true,
154+
availableFromOtherViewData to true,
155+
buttonsViewData to (multipleChoiceAvailable || availableFromOtherViewData.isNotEmpty()),
156+
).filter {
157+
it.first.isNotEmpty()
158+
}.addBetweenEach(
159+
map = { it.first },
160+
spacingProducer = { index, _, second ->
161+
if (second?.second == true) {
162+
listOf(DividerViewData("divider_$index".hashCode().toLong()))
163+
} else {
164+
null
153165
}
154-
viewData += buttonsViewData
155-
}
166+
},
167+
).flatten()
156168

157-
Result(
158-
selectedCount = selected.size,
159-
data = viewData,
160-
)
169+
return Result(
170+
selectedCount = selected.size,
171+
data = viewData,
172+
)
173+
}
174+
175+
private suspend fun mapEmpty(
176+
showAddButton: Boolean,
177+
isDarkTheme: Boolean,
178+
): Result {
179+
val viewData = mutableListOf<ViewHolderType>()
180+
viewData += if (showAddButton && recordTagInteractor.isEmpty()) {
181+
categoryViewDataMapper.mapToTagsFirstHint()
161182
} else {
162-
val viewData = mutableListOf<ViewHolderType>()
163-
viewData += if (showAddButton && recordTagInteractor.isEmpty()) {
164-
categoryViewDataMapper.mapToTagsFirstHint()
165-
} else {
166-
categoryViewDataMapper.mapToRecordTagsEmpty()
167-
}
168-
if (showAddButton) {
169-
viewData += categoryViewDataMapper.mapToRecordTagAddItem(isDarkTheme)
170-
}
171-
Result(
172-
selectedCount = 0,
173-
data = viewData,
174-
)
183+
categoryViewDataMapper.mapToRecordTagsEmpty()
184+
}
185+
if (showAddButton) {
186+
viewData += categoryViewDataMapper.mapToRecordTagAddItem(isDarkTheme)
175187
}
188+
return Result(
189+
selectedCount = 0,
190+
data = viewData,
191+
)
176192
}
177193

178194
data class Result(

domain/src/main/java/com/example/util/simpletimetracker/domain/extension/CollectionExtensions.kt

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,20 @@ inline fun <T> List<T>.replaceWith(new: T, crossinline filter: (T) -> Boolean):
5656
}
5757

5858
fun <T> List<T>.addBetweenEach(
59-
spacingProducer: (index: Int) -> T,
59+
spacingProducer: (index: Int) -> T?,
6060
): List<T> {
61-
val result = mutableListOf<T>()
61+
return this.addBetweenEach(map = { it }, spacingProducer = { index, _, _ -> spacingProducer(index) })
62+
}
63+
64+
fun <IN, OUT> List<IN>.addBetweenEach(
65+
map: (IN) -> OUT,
66+
spacingProducer: (index: Int, currentItem: IN, nextItem: IN?) -> OUT?,
67+
): List<OUT> {
68+
val result = mutableListOf<OUT>()
6269
this.forEachIndexed { index, item ->
63-
result += item
70+
result += map(item)
6471
if (index != this.lastIndex) {
65-
result += spacingProducer(index)
72+
result += spacingProducer(index, item, this.getOrNull(index + 1))
6673
}
6774
}
6875
return result

features/feature_change_record/src/main/java/com/example/util/simpletimetracker/feature_change_record/viewModel/ChangeRecordBaseViewModel.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,7 @@ abstract class ChangeRecordBaseViewModel(
919919
showAllTags = showAllTags,
920920
multipleChoiceAvailable = true,
921921
showAddButton = true,
922+
showHint = true,
922923
showArchived = false,
923924
showUntaggedButton = true,
924925
showAllTagsButton = true,

features/feature_data_edit/src/main/java/com/example/util/simpletimetracker/feature_data_edit/dialog/DataEditTagSelectionViewModel.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ class DataEditTagSelectionViewModel @Inject constructor(
101101
showAllTags = false,
102102
multipleChoiceAvailable = true,
103103
showAddButton = false,
104+
showHint = false,
104105
showArchived = true,
105106
showUntaggedButton = false,
106107
showAllTagsButton = false,

features/feature_tag_selection/src/main/java/com/example/util/simpletimetracker/feature_tag_selection/interactor/RecordTagSelectionViewDataInteractor.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class RecordTagSelectionViewDataInteractor @Inject constructor(
7777
showAllTags = showAllTags,
7878
multipleChoiceAvailable = multipleChoiceAvailable,
7979
showAddButton = false,
80+
showHint = false,
8081
showArchived = false,
8182
showUntaggedButton = true,
8283
showAllTagsButton = true,

features/feature_views/src/main/java/com/example/util/simpletimetracker/feature_views/StatisticsView.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class StatisticsView @JvmOverloads constructor(
5555
var itemDuration: String = ""
5656
set(value) {
5757
binding.tvStatisticsItemDuration.text = value
58+
binding.tvStatisticsItemDuration.isVisible = value.isNotEmpty()
5859
field = value
5960
}
6061

features/feature_views/src/main/res/layout/statistics_view_layout.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
android:id="@+id/tvStatisticsItemName"
3434
android:layout_width="0dp"
3535
android:layout_height="wrap_content"
36-
android:layout_marginStart="8dp"
36+
android:layout_marginHorizontal="8dp"
3737
android:textColor="?appLightTextColor"
3838
android:textStyle="bold"
3939
app:layout_constraintBottom_toBottomOf="parent"

0 commit comments

Comments
 (0)