• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

AdamMc331 / TOA / #111

pending completion
#111

push

github-actions

web-flow
Implementing settings UI for preferred number of tasks per day.  (#176)

1500 of 2154 relevant lines covered (69.64%)

0.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.87
app/src/main/java/com/adammcneilly/toa/addtask/domain/usecases/ProdAddTaskUseCase.kt
1
package com.adammcneilly.toa.addtask.domain.usecases
2

3
import com.adammcneilly.toa.addtask.domain.model.AddTaskResult
4
import com.adammcneilly.toa.core.models.Task
5
import com.adammcneilly.toa.preferences.UserPreferences
6
import com.adammcneilly.toa.task.api.TaskRepository
7
import kotlinx.coroutines.flow.first
8
import java.time.Instant
9
import java.time.LocalDate
10
import java.time.ZoneId
11
import javax.inject.Inject
12

13
class ProdAddTaskUseCase @Inject constructor(
1✔
14
    private val taskRepository: TaskRepository,
1✔
15
    private val userPreferences: UserPreferences,
1✔
16
) : AddTaskUseCase {
17

18
    @Suppress("ReturnCount")
19
    override suspend fun invoke(
1✔
20
        task: Task,
21
        ignoreTaskLimits: Boolean,
22
    ): AddTaskResult {
23
        val sanitizedTask = task.copy(
1✔
24
            description = task.description.trim(),
1✔
25
        )
26

27
        val validationResult = validateInput(sanitizedTask)
1✔
28

29
        if (validationResult != null) {
1✔
30
            return validationResult
1✔
31
        }
32

33
        if (!ignoreTaskLimits) {
1✔
34
            val preferenceCheckResult = ensureNumTasksWithinPreferences(task, taskRepository, userPreferences)
1✔
35

36
            if (preferenceCheckResult != null) {
1✔
37
                return preferenceCheckResult
1✔
38
            }
39
        }
40

41
        val result = taskRepository.addTask(sanitizedTask)
1✔
42

43
        return result.fold(
1✔
44
            onSuccess = {
45
                AddTaskResult.Success
1✔
46
            },
47
            onFailure = {
48
                AddTaskResult.Failure.Unknown
×
49
            },
50
        )
51
    }
52

53
    private suspend fun ensureNumTasksWithinPreferences(
54
        task: Task,
55
        taskRepository: TaskRepository,
56
        userPreferences: UserPreferences,
57
    ): AddTaskResult.Failure.MaxTasksPerDayExceeded? {
58
        if (!userPreferences.getPreferredNumTasksPerDayEnabled()) {
1✔
59
            return null
1✔
60
        }
61

62
        val preferredNumTasks = userPreferences.getPreferredNumTasksPerDay() ?: return null
1✔
63

64
        val incompleteTaskList = taskRepository.fetchTasksForDate(
1✔
65
            dateMillis = task.scheduledDateMillis,
1✔
66
            completed = false,
1✔
67
        ).first().getOrNull()
1✔
68

69
        val numIncompleteTasks = incompleteTaskList?.size ?: 0
1✔
70

71
        return if (numIncompleteTasks >= preferredNumTasks) {
1✔
72
            AddTaskResult.Failure.MaxTasksPerDayExceeded
1✔
73
        } else {
74
            null
×
75
        }
76
    }
77

78
    /**
79
     * Since it's no longer possible to select a date in the past (our date picker validates this),
80
     * we can simplify this to only validate that the description is not empty.
81
     */
82
    private fun validateInput(task: Task): AddTaskResult.Failure.InvalidInput? {
83
        val emptyDescription = task.description.isBlank()
1✔
84

85
        val scheduledDate = Instant
1✔
86
            .ofEpochMilli(task.scheduledDateMillis)
1✔
87
            .atZone(ZoneId.systemDefault())
1✔
88
            .toLocalDate()
1✔
89
        val scheduledDateInPast = scheduledDate.isBefore(LocalDate.now())
1✔
90

91
        return if (emptyDescription || scheduledDateInPast) {
1✔
92
            AddTaskResult.Failure.InvalidInput(
1✔
93
                emptyDescription = emptyDescription,
1✔
94
                scheduledDateInPast = scheduledDateInPast,
1✔
95
            )
96
        } else {
97
            null
1✔
98
        }
99
    }
100
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc