Skip to content

Commit

Permalink
add activity suggestions module
Browse files Browse the repository at this point in the history
  • Loading branch information
Razeeman committed Dec 30, 2024
1 parent b408f93 commit b301eac
Show file tree
Hide file tree
Showing 34 changed files with 870 additions and 21 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ Simple app that helps track how much time you spend on all the useless activitie
│ ├── feature_settings # One of main tabs, settings.
│ ├── feature_statistics # One of main tabs, statistics.
│ ├── feature_statistics_detail # Screen showing detailed statistics.
│ ├── feature_suggestions # Screen for activity suggestions.
│ ├── feature_tag_selection # Screen for selecting tags.
│ ├── feature_views # Custom views.
│ ├── feature_wear # Phone app logic to connect to wear app.
Expand Down
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ dependencies {
implementation(project(":feature_goals"))
implementation(project(":feature_pomodoro"))
implementation(project(":feature_complex_rules"))
implementation(project(":feature_suggestions"))
implementation(project(":feature_change_complex_rule"))
implementation(project(":feature_change_goals"))
implementation(project(":feature_change_goals:api"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import com.example.util.simpletimetracker.feature_statistics_detail.view.Statist
import com.example.util.simpletimetracker.navigation.NavigationData
import com.example.util.simpletimetracker.navigation.bundleCreator.BundleCreator
import com.example.util.simpletimetracker.navigation.bundleCreator.bundleCreatorDelegate
import com.example.util.simpletimetracker.navigation.params.screen.ActivitySuggestionsParams
import com.example.util.simpletimetracker.navigation.params.screen.ArchiveParams
import com.example.util.simpletimetracker.navigation.params.screen.CategoriesParams
import com.example.util.simpletimetracker.navigation.params.screen.ChangeActivityFilterParams
Expand Down Expand Up @@ -162,6 +163,16 @@ class NavigationScreenMapModule {
)
}

@IntoMap
@Provides
@ScreenKey(ActivitySuggestionsParams::class)
fun activitySuggestions(): NavigationData {
return NavigationData(
R.id.action_to_activitySuggestionsFragment,
BundleCreator.empty(),
)
}

@IntoMap
@Provides
@ScreenKey(ChangeCategoryFromTagsParams::class)
Expand Down
15 changes: 14 additions & 1 deletion app/src/main/res/navigation/nav_graph.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right" />

<action
android:id="@+id/action_to_activitySuggestionsFragment"
app:destination="@id/activitySuggestionsFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right" />

<action
android:id="@+id/action_to_statisticsDetailFragment"
app:destination="@id/statisticsDetailFragment"
Expand Down Expand Up @@ -210,8 +218,13 @@
<fragment
android:id="@+id/complexRulesFragment"
android:name="com.example.util.simpletimetracker.feature_complex_rules.view.ComplexRulesFragment"
android:label="DataEditFragment"
android:label="ComplexRulesFragment"
tools:layout="@layout/complex_rules_fragment" />
<fragment
android:id="@+id/activitySuggestionsFragment"
android:name="com.example.util.simpletimetracker.feature_suggestions.view.ActivitySuggestionsFragment"
android:label="ActivitySuggestionsFragment"
tools:layout="@layout/activity_suggestions_fragment" />
<fragment
android:id="@+id/changeComplexRuleFragment"
android:name="com.example.util.simpletimetracker.feature_change_complex_rule.view.ChangeComplexRuleFragment"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.example.util.simpletimetracker.core.R
import com.example.util.simpletimetracker.core.interactor.GetCurrentRecordsDurationInteractor
import com.example.util.simpletimetracker.core.repo.ResourceRepo
import com.example.util.simpletimetracker.domain.recordType.extension.getDaily
import com.example.util.simpletimetracker.domain.extension.orFalse
import com.example.util.simpletimetracker.domain.extension.orZero
import com.example.util.simpletimetracker.domain.recordType.extension.value
import com.example.util.simpletimetracker.domain.color.model.AppColor
Expand Down Expand Up @@ -95,7 +96,7 @@ class RecordTypeViewDataMapper @Inject constructor(
}

fun mapToAddItem(
numberOfCards: Int,
numberOfCards: Int?,
isDarkTheme: Boolean,
): RunningRecordTypeSpecialViewData {
return mapToSpecial(
Expand Down Expand Up @@ -209,7 +210,7 @@ class RecordTypeViewDataMapper @Inject constructor(
type: RunningRecordTypeSpecialViewData.Type,
@StringRes name: Int,
icon: RecordTypeIcon,
numberOfCards: Int,
numberOfCards: Int?, // TODO SUG revert?
isDarkTheme: Boolean,
checkState: GoalCheckmarkView.CheckState,
): RunningRecordTypeSpecialViewData {
Expand All @@ -218,9 +219,9 @@ class RecordTypeViewDataMapper @Inject constructor(
name = name.let(resourceRepo::getString),
iconId = icon,
color = colorMapper.toInactiveColor(isDarkTheme),
width = recordTypeCardSizeMapper.toCardWidth(numberOfCards),
height = recordTypeCardSizeMapper.toCardHeight(numberOfCards),
asRow = recordTypeCardSizeMapper.toCardAsRow(numberOfCards),
width = numberOfCards?.let(recordTypeCardSizeMapper::toCardWidth),
height = numberOfCards?.let(recordTypeCardSizeMapper::toCardHeight),
asRow = numberOfCards?.let(recordTypeCardSizeMapper::toCardAsRow).orFalse(),
checkState = checkState,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class CalculateAdjacentActivitiesInteractor @Inject constructor() {
fun calculateNextActivities(
typeIds: List<Long>,
records: List<Record>,
maxCount: Int,
): Map<Long, List<CalculationResult>> {
val counts = mutableMapOf<Long, MutableMap<Long, Long>>()
val recordsSorted = records.sortedBy { it.timeStarted }
Expand Down Expand Up @@ -40,7 +41,7 @@ class CalculateAdjacentActivitiesInteractor @Inject constructor() {
return counts.mapValues { (_, counts) ->
counts.keys
.sortedByDescending { counts[it].orZero() }
.take(MAX_COUNT)
.take(maxCount)
.map { CalculationResult(it, counts[it].orZero()) }
}
}
Expand All @@ -49,6 +50,7 @@ class CalculateAdjacentActivitiesInteractor @Inject constructor() {
fun calculateMultitasking(
typeId: Long,
records: List<RecordBase>,
maxCount: Int,
): List<CalculationResult> {
val counts = mutableMapOf<Long, Long>()

Expand Down Expand Up @@ -76,16 +78,12 @@ class CalculateAdjacentActivitiesInteractor @Inject constructor() {

return counts.keys
.sortedByDescending { counts[it].orZero() }
.take(MAX_COUNT)
.take(maxCount)
.map { CalculationResult(it, counts[it].orZero()) }
}

data class CalculationResult(
val typeId: Long,
val count: Long,
)

companion object {
private const val MAX_COUNT = 5
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class CalculateAdjacentActivitiesInteractorTest(
val actual = subject.calculateNextActivities(
typeIds = input.first,
records = input.second,
maxCount = 5,
)

assertEquals(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.example.util.simpletimetracker.feature_base_adapter.hint

import android.view.Gravity
import androidx.core.view.updatePadding
import com.example.util.simpletimetracker.feature_base_adapter.createRecyclerBindingAdapterDelegate
import com.example.util.simpletimetracker.feature_views.extension.dpToPx
Expand All @@ -10,6 +11,13 @@ fun createHintAdapterDelegate() = createRecyclerBindingAdapterDelegate<ViewData,
Binding::inflate,
) { binding, item, _ ->

fun ViewData.Gravity.toViewData(): Int {
return when (this) {
ViewData.Gravity.CENTER -> Gravity.CENTER
ViewData.Gravity.START -> Gravity.START
}
}

with(binding) {
item as ViewData

Expand All @@ -18,5 +26,6 @@ fun createHintAdapterDelegate() = createRecyclerBindingAdapterDelegate<ViewData,
bottom = item.paddingBottom.dpToPx(),
)
tvHintItemText.text = item.text
tvHintItemText.gravity = item.gravity.toViewData()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@ data class HintViewData(
val text: String,
val paddingTop: Int = 8,
val paddingBottom: Int = 8,
val gravity: Gravity = Gravity.CENTER,
) : ViewHolderType {

override fun getUniqueId(): Long = text.hashCode().toLong()

override fun isValidType(other: ViewHolderType): Boolean = other is HintViewData

enum class Gravity {
CENTER,
START,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ fun createRunningRecordTypeSpecialAdapterDelegate(
item as ViewData

layoutParams = layoutParams.also { params ->
params.width = item.width.dpToPx()
params.height = item.height.dpToPx()
item.width?.dpToPx()?.let { params.width = it }
item.height?.dpToPx()?.let { params.height = it }
}

itemIsRow = item.asRow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ data class RunningRecordTypeSpecialViewData(
val name: String,
val iconId: RecordTypeIcon,
@ColorInt val color: Int,
val width: Int,
val height: Int,
val width: Int?,
val height: Int?,
val asRow: Boolean = false,
val checkState: CheckState = CheckState.HIDDEN,
) : ViewHolderType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
app:layout_constraintBottom_toTopOf="@id/dividerChangeRecordButton"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0"
tools:visibility="gone">
tools:visibility="visible">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
Expand Down Expand Up @@ -519,7 +519,7 @@
app:layout_constraintTop_toBottomOf="@id/containerChangeRecordMain"
tools:itemCount="1"
tools:listitem="@layout/change_record_comment_field_item"
tools:visibility="visible" />
tools:visibility="gone" />

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvChangeRecordAction"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
android:textColor="?appTextHintColor"
app:layout_constraintTop_toBottomOf="@id/tvComplexRulesTitle" />

<com.example.util.simpletimetracker.feature_views.DividerView
<com.example.util.simpletimetracker.feature_views.DividerFullView
android:id="@+id/dividerComplexRules"
android:layout_width="match_parent"
android:layout_height="wrap_content"
Expand All @@ -40,6 +40,7 @@
android:layout_width="match_parent"
android:layout_height="0dp"
android:clipToPadding="false"
android:paddingTop="6dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/dividerComplexRules"
tools:listitem="@layout/item_complex_rule_layout" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class TypesSelectionViewModel @Inject constructor(
}

fun onShowAllClick() {
dataIdsSelected.clear()
dataIdsSelected.addAll(viewDataCache.map(TypesSelectionCacheHolder::id))
updateViewData()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ enum class SettingsBlock {
AdditionalSendEvents,
AdditionalDataEdit,
AdditionalComplexRules,
AdditionalActivitySuggestions,
AdditionalBottom,

BackupTop,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,11 @@ class SettingsAdditionalViewDataInteractor @Inject constructor(
block = SettingsBlock.AdditionalComplexRules,
title = resourceRepo.getString(R.string.settings_complex_rules),
subtitle = "",
)
result += SettingsTextViewData(
block = SettingsBlock.AdditionalActivitySuggestions,
title = resourceRepo.getString(R.string.settings_activity_suggestions),
subtitle = "",
dividerIsVisible = false,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import com.example.util.simpletimetracker.feature_settings.mapper.SettingsAutoma
import com.example.util.simpletimetracker.feature_settings.mapper.SettingsMapper
import com.example.util.simpletimetracker.feature_settings.viewModel.SettingsViewModel
import com.example.util.simpletimetracker.navigation.Router
import com.example.util.simpletimetracker.navigation.params.screen.ActivitySuggestionsParams
import com.example.util.simpletimetracker.navigation.params.screen.ComplexRulesParams
import com.example.util.simpletimetracker.navigation.params.screen.DataEditParams
import com.example.util.simpletimetracker.navigation.params.screen.DurationDialogParams
Expand Down Expand Up @@ -71,6 +72,7 @@ class SettingsAdditionalViewModelDelegate @Inject constructor(
SettingsBlock.AdditionalKeepScreenOn -> onKeepScreenOnClicked()
SettingsBlock.AdditionalDataEdit -> onDataEditClick()
SettingsBlock.AdditionalComplexRules -> onComplexRulesClick()
SettingsBlock.AdditionalActivitySuggestions -> onActivitySuggestionsClick()
else -> {
// Do nothing
}
Expand Down Expand Up @@ -262,6 +264,10 @@ class SettingsAdditionalViewModelDelegate @Inject constructor(
router.navigate(ComplexRulesParams)
}

private fun onActivitySuggestionsClick() {
router.navigate(ActivitySuggestionsParams)
}

private fun onAutomatedTrackingHelpClick() {
delegateScope.launch {
val isDarkTheme = prefsInteractor.getDarkMode()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ class StatisticsDetailAdjacentActivitiesInteractor @Inject constructor(
val recordTypes = recordTypeInteractor.getAll().associateBy(RecordType::id)
val actualRecords = getRecords(rangeLength, rangePosition)
val nextActivitiesIds = calculateAdjacentActivitiesInteractor
.calculateNextActivities(listOf(typeId), actualRecords)
.calculateNextActivities(listOf(typeId), actualRecords, MAX_COUNT)
.getOrElse(typeId) { emptyList() }
val multitaskingActivitiesIds = calculateAdjacentActivitiesInteractor
.calculateMultitasking(typeId, actualRecords)
.calculateMultitasking(typeId, actualRecords, MAX_COUNT)

fun mapPreviews(typeToCounts: List<CalculationResult>): List<ViewHolderType> {
val total = typeToCounts.sumOf(CalculationResult::count)
Expand Down Expand Up @@ -129,4 +129,8 @@ class StatisticsDetailAdjacentActivitiesInteractor @Inject constructor(
private fun getEmptyViewData(): List<ViewHolderType> {
return emptyList()
}

companion object {
private const val MAX_COUNT = 5
}
}
1 change: 1 addition & 0 deletions features/feature_suggestions/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
21 changes: 21 additions & 0 deletions features/feature_suggestions/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import com.example.util.simpletimetracker.Base
import com.example.util.simpletimetracker.applyAndroidLibrary

plugins {
alias(libs.plugins.gradleLibrary)
alias(libs.plugins.kotlin)
alias(libs.plugins.ksp)
alias(libs.plugins.hilt)
}

applyAndroidLibrary()

android {
namespace = "${Base.namespace}.feature_suggestions"
}

dependencies {
implementation(project(":core"))
implementation(libs.google.dagger)
ksp(libs.kapt.dagger)
}
5 changes: 5 additions & 0 deletions features/feature_suggestions/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<application android:theme="@style/AppTheme" />

</manifest>
Loading

0 comments on commit b301eac

Please sign in to comment.