Skip to content

Commit 13005a7

Browse files
committed
add an option to ignore newly added items on statistics widget
1 parent b73815f commit 13005a7

33 files changed

Lines changed: 396 additions & 168 deletions

File tree

data_local/src/main/java/com/example/util/simpletimetracker/data_local/prefs/PrefsRepoImpl.kt

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -419,9 +419,13 @@ class PrefsRepoImpl @Inject constructor(
419419
is RangeLength.Custom -> 0 // Not possible
420420
}
421421
val rangeDataLastDays = (data.rangeLength as? RangeLength.Last)?.days
422-
val filteredTypesData = data.filteredTypes.map(Long::toString).toSet()
423-
val filteredCategoriesData = data.filteredCategories.map(Long::toString).toSet()
424-
val filteredTagsData = data.filteredTags.map(Long::toString).toSet()
422+
val filteredTypesData = data.typeIds.map(Long::toString).toSet()
423+
val filteredCategoriesData = data.categoryIds.map(Long::toString).toSet()
424+
val filteredTagsData = data.tagIds.map(Long::toString).toSet()
425+
val filteringType = when (data.filteringType) {
426+
StatisticsWidgetData.FilterType.FILTER -> 0
427+
StatisticsWidgetData.FilterType.SELECT -> 1
428+
}
425429

426430
prefs.edit()
427431
.putInt(KEY_STATISTICS_WIDGET_FILTER_TYPE + widgetId, filterTypeData)
@@ -434,6 +438,7 @@ class PrefsRepoImpl @Inject constructor(
434438
.putStringSet(KEY_STATISTICS_WIDGET_FILTERED_TYPES + widgetId, filteredTypesData)
435439
.putStringSet(KEY_STATISTICS_WIDGET_FILTERED_CATEGORIES + widgetId, filteredCategoriesData)
436440
.putStringSet(KEY_STATISTICS_WIDGET_FILTERED_TAGS + widgetId, filteredTagsData)
441+
.putInt(KEY_STATISTICS_WIDGET_FILTERING_TYPE + widgetId, filteringType)
437442
.apply()
438443
}
439444

@@ -465,13 +470,19 @@ class PrefsRepoImpl @Inject constructor(
465470
val filteredTags = prefs
466471
.getStringSet(KEY_STATISTICS_WIDGET_FILTERED_TAGS + widgetId, emptySet())
467472
?.mapNotNull { it.toLongOrNull() }.orEmpty().toSet()
473+
val filteringType = when(prefs.getInt(KEY_STATISTICS_WIDGET_FILTERING_TYPE + widgetId, 0)) {
474+
0 -> StatisticsWidgetData.FilterType.FILTER
475+
1 -> StatisticsWidgetData.FilterType.SELECT
476+
else -> StatisticsWidgetData.FilterType.FILTER
477+
}
468478

469479
return StatisticsWidgetData(
470480
chartFilterType = filterType,
471481
rangeLength = range,
472-
filteredTypes = filteredTypes,
473-
filteredCategories = filteredCategories,
474-
filteredTags = filteredTags,
482+
typeIds = filteredTypes,
483+
categoryIds = filteredCategories,
484+
tagIds = filteredTags,
485+
filteringType = filteringType,
475486
)
476487
}
477488

@@ -647,6 +658,7 @@ class PrefsRepoImpl @Inject constructor(
647658
private const val KEY_STATISTICS_WIDGET_FILTER_TYPE = "statistics_widget_filter_type_"
648659
private const val KEY_STATISTICS_WIDGET_RANGE = "statistics_widget_range_"
649660
private const val KEY_STATISTICS_WIDGET_RANGE_LAST_DAYS = "statistics_widget_range_last_days_"
661+
private const val KEY_STATISTICS_WIDGET_FILTERING_TYPE = "statistics_widget_filtering_type_"
650662
private const val KEY_QUICK_SETTINGS_WIDGET_TYPE = "quick_settings_widget_type_"
651663

652664
// Removed
Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
package com.example.util.simpletimetracker.domain.statistics.model
22

3+
// Ids are either filtered or selected,
4+
// depending on filtering type.
35
data class StatisticsWidgetData(
46
val chartFilterType: ChartFilterType,
57
val rangeLength: RangeLength,
6-
val filteredTypes: Set<Long>,
7-
val filteredCategories: Set<Long>,
8-
val filteredTags: Set<Long>,
9-
)
8+
val typeIds: Set<Long>,
9+
val categoryIds: Set<Long>,
10+
val tagIds: Set<Long>,
11+
val filteringType: FilterType,
12+
) {
13+
14+
enum class FilterType {
15+
FILTER,
16+
SELECT,
17+
}
18+
}

features/feature_widget/src/main/java/com/example/util/simpletimetracker/feature_widget/statistics/WidgetStatisticsChartProvider.kt

Lines changed: 9 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -14,58 +14,42 @@ import android.widget.RemoteViews
1414
import androidx.core.text.bold
1515
import com.example.util.simpletimetracker.core.extension.allowDiskRead
1616
import com.example.util.simpletimetracker.core.extension.allowVmViolations
17-
import com.example.util.simpletimetracker.core.interactor.StatisticsChartViewDataInteractor
18-
import com.example.util.simpletimetracker.core.interactor.StatisticsMediator
19-
import com.example.util.simpletimetracker.core.mapper.TimeMapper
2017
import com.example.util.simpletimetracker.core.repo.ResourceRepo
2118
import com.example.util.simpletimetracker.core.utils.PendingIntents
2219
import com.example.util.simpletimetracker.core.utils.SHORTCUT_NAVIGATION_KEY
2320
import com.example.util.simpletimetracker.core.utils.SHORTCUT_NAVIGATION_STATISTICS
2421
import com.example.util.simpletimetracker.domain.prefs.interactor.PrefsInteractor
25-
import com.example.util.simpletimetracker.domain.recordType.interactor.RecordTypeInteractor
26-
import com.example.util.simpletimetracker.domain.statistics.model.ChartFilterType
27-
import com.example.util.simpletimetracker.domain.recordType.model.RecordType
2822
import com.example.util.simpletimetracker.feature_views.extension.dpToPx
2923
import com.example.util.simpletimetracker.feature_views.extension.getBitmapFromView
3024
import com.example.util.simpletimetracker.feature_views.extension.measureExactly
3125
import com.example.util.simpletimetracker.feature_views.extension.pxToDp
3226
import com.example.util.simpletimetracker.feature_views.viewData.RecordTypeIcon
3327
import com.example.util.simpletimetracker.feature_widget.R
3428
import com.example.util.simpletimetracker.feature_widget.common.WidgetViewsHolder
29+
import com.example.util.simpletimetracker.feature_widget.statistics.interactor.WidgetStatisticsViewDataInteractor
3530
import com.example.util.simpletimetracker.navigation.Router
3631
import dagger.hilt.android.AndroidEntryPoint
37-
import kotlinx.coroutines.Dispatchers
3832
import kotlinx.coroutines.MainScope
3933
import kotlinx.coroutines.launch
40-
import kotlinx.coroutines.withContext
4134
import javax.inject.Inject
4235

4336
@AndroidEntryPoint
4437
class WidgetStatisticsChartProvider : AppWidgetProvider() {
4538

46-
@Inject
47-
lateinit var statisticsChartViewDataInteractor: StatisticsChartViewDataInteractor
48-
49-
@Inject
50-
lateinit var statisticsMediator: StatisticsMediator
51-
5239
@Inject
5340
lateinit var router: Router
5441

5542
@Inject
5643
lateinit var prefsInteractor: PrefsInteractor
5744

58-
@Inject
59-
lateinit var recordTypeInteractor: RecordTypeInteractor
60-
6145
@Inject
6246
lateinit var resourceRepo: ResourceRepo
6347

6448
@Inject
65-
lateinit var timeMapper: TimeMapper
49+
lateinit var widgetViewsHolder: WidgetViewsHolder
6650

6751
@Inject
68-
lateinit var widgetViewsHolder: WidgetViewsHolder
52+
lateinit var widgetStatisticsViewDataInteractor: WidgetStatisticsViewDataInteractor
6953

7054
override fun onUpdate(
7155
context: Context?,
@@ -128,54 +112,12 @@ class WidgetStatisticsChartProvider : AppWidgetProvider() {
128112
): View {
129113
val backgroundTransparency = prefsInteractor.getWidgetBackgroundTransparencyPercent()
130114

131-
val (chart, total) = withContext(Dispatchers.IO) {
132-
val isDarkTheme = prefsInteractor.getDarkMode()
133-
val useProportionalMinutes = prefsInteractor.getUseProportionalMinutes()
134-
val showSeconds = prefsInteractor.getShowSeconds()
135-
val firstDayOfWeek = prefsInteractor.getFirstDayOfWeek()
136-
val startOfDayShift = prefsInteractor.getStartOfDayShift()
137-
val widgetData = prefsInteractor.getStatisticsWidget(appWidgetId)
138-
val types = recordTypeInteractor.getAll().associateBy(RecordType::id)
139-
140-
val filterType = widgetData.chartFilterType
141-
val filteredIds = when (filterType) {
142-
ChartFilterType.ACTIVITY -> widgetData.filteredTypes
143-
ChartFilterType.CATEGORY -> widgetData.filteredCategories
144-
ChartFilterType.RECORD_TAG -> widgetData.filteredTags
145-
}.toList()
146-
val rangeLength = widgetData.rangeLength
147-
148-
val dataHolders = statisticsMediator.getDataHolders(
149-
filterType = filterType,
150-
types = types,
151-
)
152-
val range = timeMapper.getRangeStartAndEnd(
153-
rangeLength = rangeLength,
154-
shift = 0,
155-
firstDayOfWeek = firstDayOfWeek,
156-
startOfDayShift = startOfDayShift,
157-
)
158-
val statistics = statisticsMediator.getStatistics(
159-
filterType = filterType,
160-
filteredIds = filteredIds,
161-
range = range,
162-
)
163-
val chart = statisticsChartViewDataInteractor.getChart(
164-
filterType = filterType,
165-
filteredIds = filteredIds,
166-
statistics = statistics,
167-
dataHolders = dataHolders,
168-
types = types,
169-
isDarkTheme = isDarkTheme,
170-
)
171-
val total: String = statisticsMediator.getStatisticsTotalTracked(
172-
statistics = statistics,
173-
filteredIds = filteredIds,
174-
useProportionalMinutes = useProportionalMinutes,
175-
showSeconds = showSeconds,
176-
)
177-
chart to total
178-
}
115+
val data = widgetStatisticsViewDataInteractor.getViewData(
116+
appWidgetId = appWidgetId,
117+
)
118+
val chart = data.chart
119+
val total = data.total
120+
179121
val totalTracked = SpannableStringBuilder()
180122
.append(resourceRepo.getString(R.string.statistics_total_tracked_short))
181123
.append("\n")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.example.util.simpletimetracker.feature_widget.statistics.interactor
2+
3+
import com.example.util.simpletimetracker.domain.base.UNCATEGORIZED_ITEM_ID
4+
import com.example.util.simpletimetracker.domain.base.UNTRACKED_ITEM_ID
5+
import com.example.util.simpletimetracker.domain.statistics.model.ChartFilterType
6+
import com.example.util.simpletimetracker.domain.statistics.model.StatisticsWidgetData
7+
import javax.inject.Inject
8+
9+
class WidgetStatisticsIdsInteractor @Inject constructor() {
10+
11+
fun getAllTypeIds(
12+
typeIds: Set<Long>,
13+
): Set<Long> {
14+
return typeIds + UNTRACKED_ITEM_ID
15+
}
16+
17+
fun getAllCategoryIds(
18+
categoryIds: Set<Long>,
19+
): Set<Long> {
20+
return categoryIds + UNTRACKED_ITEM_ID + UNCATEGORIZED_ITEM_ID
21+
}
22+
23+
fun getAllTagIds(
24+
tagIds: Set<Long>,
25+
): Set<Long> {
26+
return tagIds + UNTRACKED_ITEM_ID + UNCATEGORIZED_ITEM_ID
27+
}
28+
29+
suspend fun getActualFilteredIds(
30+
widgetData: StatisticsWidgetData,
31+
typeIds: suspend () -> Set<Long>,
32+
categoryIds: suspend () -> Set<Long>,
33+
tagIds: suspend () -> Set<Long>,
34+
): List<Long> {
35+
val filterType = widgetData.chartFilterType
36+
37+
val widgetItemIds = when (filterType) {
38+
ChartFilterType.ACTIVITY -> widgetData.typeIds
39+
ChartFilterType.CATEGORY -> widgetData.categoryIds
40+
ChartFilterType.RECORD_TAG -> widgetData.tagIds
41+
}.toList()
42+
43+
return when (widgetData.filteringType) {
44+
StatisticsWidgetData.FilterType.FILTER -> {
45+
widgetItemIds
46+
}
47+
StatisticsWidgetData.FilterType.SELECT -> {
48+
val allIds = when (filterType) {
49+
ChartFilterType.ACTIVITY -> getAllTypeIds(typeIds.invoke())
50+
ChartFilterType.CATEGORY -> getAllCategoryIds(categoryIds.invoke())
51+
ChartFilterType.RECORD_TAG -> getAllTagIds(tagIds.invoke())
52+
}
53+
allIds.filter { it !in widgetItemIds }
54+
}
55+
}
56+
}
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package com.example.util.simpletimetracker.feature_widget.statistics.interactor
2+
3+
import com.example.util.simpletimetracker.core.interactor.StatisticsChartViewDataInteractor
4+
import com.example.util.simpletimetracker.core.interactor.StatisticsMediator
5+
import com.example.util.simpletimetracker.core.mapper.TimeMapper
6+
import com.example.util.simpletimetracker.domain.category.interactor.CategoryInteractor
7+
import com.example.util.simpletimetracker.domain.category.model.Category
8+
import com.example.util.simpletimetracker.domain.prefs.interactor.PrefsInteractor
9+
import com.example.util.simpletimetracker.domain.recordTag.interactor.RecordTagInteractor
10+
import com.example.util.simpletimetracker.domain.recordTag.model.RecordTag
11+
import com.example.util.simpletimetracker.domain.recordType.interactor.RecordTypeInteractor
12+
import com.example.util.simpletimetracker.domain.recordType.model.RecordType
13+
import com.example.util.simpletimetracker.feature_views.pieChart.PiePortion
14+
import kotlinx.coroutines.Dispatchers
15+
import kotlinx.coroutines.withContext
16+
import javax.inject.Inject
17+
18+
class WidgetStatisticsViewDataInteractor @Inject constructor(
19+
private val statisticsChartViewDataInteractor: StatisticsChartViewDataInteractor,
20+
private val widgetStatisticsIdsInteractor: WidgetStatisticsIdsInteractor,
21+
private val statisticsMediator: StatisticsMediator,
22+
private val prefsInteractor: PrefsInteractor,
23+
private val recordTypeInteractor: RecordTypeInteractor,
24+
private val categoryInteractor: CategoryInteractor,
25+
private val recordTagInteractor: RecordTagInteractor,
26+
private val timeMapper: TimeMapper,
27+
) {
28+
29+
suspend fun getViewData(
30+
appWidgetId: Int,
31+
): Result = withContext(Dispatchers.IO) {
32+
val isDarkTheme = prefsInteractor.getDarkMode()
33+
val useProportionalMinutes = prefsInteractor.getUseProportionalMinutes()
34+
val showSeconds = prefsInteractor.getShowSeconds()
35+
val firstDayOfWeek = prefsInteractor.getFirstDayOfWeek()
36+
val startOfDayShift = prefsInteractor.getStartOfDayShift()
37+
val widgetData = prefsInteractor.getStatisticsWidget(appWidgetId)
38+
val types = recordTypeInteractor.getAll()
39+
val typesMap = types.associateBy(RecordType::id)
40+
val filterType = widgetData.chartFilterType
41+
val rangeLength = widgetData.rangeLength
42+
val filteredIds = widgetStatisticsIdsInteractor.getActualFilteredIds(
43+
widgetData = widgetData,
44+
typeIds = { types.map(RecordType::id).toSet() },
45+
categoryIds = { categoryInteractor.getAll().map(Category::id).toSet() },
46+
tagIds = { recordTagInteractor.getAll().map(RecordTag::id).toSet() },
47+
)
48+
49+
val dataHolders = statisticsMediator.getDataHolders(
50+
filterType = filterType,
51+
types = typesMap,
52+
)
53+
val range = timeMapper.getRangeStartAndEnd(
54+
rangeLength = rangeLength,
55+
shift = 0,
56+
firstDayOfWeek = firstDayOfWeek,
57+
startOfDayShift = startOfDayShift,
58+
)
59+
val statistics = statisticsMediator.getStatistics(
60+
filterType = filterType,
61+
filteredIds = filteredIds,
62+
range = range,
63+
)
64+
val chart = statisticsChartViewDataInteractor.getChart(
65+
filterType = filterType,
66+
filteredIds = filteredIds,
67+
statistics = statistics,
68+
dataHolders = dataHolders,
69+
types = typesMap,
70+
isDarkTheme = isDarkTheme,
71+
)
72+
val total: String = statisticsMediator.getStatisticsTotalTracked(
73+
statistics = statistics,
74+
filteredIds = filteredIds,
75+
useProportionalMinutes = useProportionalMinutes,
76+
showSeconds = showSeconds,
77+
)
78+
79+
Result(
80+
chart = chart,
81+
total = total,
82+
)
83+
}
84+
85+
data class Result(
86+
val chart: List<PiePortion>,
87+
val total: String,
88+
)
89+
}

0 commit comments

Comments
 (0)