Skip to content

Commit 10484b7

Browse files
authored
Merge branch 'Razeeman:dev' into dev
2 parents 89a178b + 9a49699 commit 10484b7

57 files changed

Lines changed: 707 additions & 637 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 3 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Tests
1+
name: Check
22
on:
33
pull_request:
44
branches:
@@ -11,7 +11,7 @@ on:
1111
paths-ignore:
1212
- '**.md'
1313
jobs:
14-
tests:
14+
check:
1515
runs-on: ubuntu-latest
1616
timeout-minutes: 60
1717

@@ -23,50 +23,10 @@ jobs:
2323
uses: actions/setup-java@v4
2424
with:
2525
distribution: 'zulu'
26-
java-version: '17'
26+
java-version: '21'
2727

2828
- name: Run style check
2929
run: ./gradlew ktlintCheck
3030

3131
- name: Run tests
3232
run: ./gradlew test testDebugUnitTest --stacktrace
33-
34-
android_tests:
35-
runs-on: ubuntu-latest
36-
timeout-minutes: 120
37-
strategy:
38-
fail-fast: false
39-
matrix:
40-
api-level: [21, 23, 29, 32, 34]
41-
42-
steps:
43-
- name: Check out code
44-
uses: actions/checkout@v4
45-
46-
- name: Setup Java
47-
uses: actions/setup-java@v4
48-
with:
49-
distribution: 'zulu'
50-
java-version: '17'
51-
52-
- name: Enable KVM
53-
run: |
54-
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
55-
sudo udevadm control --reload-rules
56-
sudo udevadm trigger --name-match=kvm
57-
58-
- name: Setup Android SDK
59-
uses: android-actions/setup-android@v3
60-
61-
- name: Run tests
62-
uses: reactivecircus/android-emulator-runner@v2
63-
with:
64-
api-level: ${{ matrix.api-level }}
65-
target: google_apis
66-
arch: x86_64
67-
disable-animations: true
68-
script: |
69-
adb shell settings put global window_animation_scale 0
70-
adb shell settings put global transition_animation_scale 0
71-
adb shell settings put global animator_duration_scale 0
72-
./gradlew app:connectedPlayDebugAndroidTest --stacktrace
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Check_UI
2+
on:
3+
workflow_dispatch
4+
jobs:
5+
check_ui:
6+
runs-on: ubuntu-latest
7+
timeout-minutes: 120
8+
strategy:
9+
fail-fast: false
10+
matrix:
11+
api-level: [21, 23, 29, 32, 34]
12+
13+
steps:
14+
- name: Check out code
15+
uses: actions/checkout@v4
16+
17+
- name: Setup Java
18+
uses: actions/setup-java@v4
19+
with:
20+
distribution: 'zulu'
21+
java-version: '21'
22+
23+
- name: Enable KVM
24+
run: |
25+
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
26+
sudo udevadm control --reload-rules
27+
sudo udevadm trigger --name-match=kvm
28+
29+
- name: Setup Android SDK
30+
uses: android-actions/setup-android@v3
31+
32+
- name: Run tests
33+
uses: reactivecircus/android-emulator-runner@v2
34+
with:
35+
api-level: ${{ matrix.api-level }}
36+
target: google_apis
37+
arch: x86_64
38+
disable-animations: true
39+
script: |
40+
adb shell settings put global window_animation_scale 0
41+
adb shell settings put global transition_animation_scale 0
42+
adb shell settings put global animator_duration_scale 0
43+
./gradlew app:connectedPlayDebugAndroidTest --stacktrace

core/src/main/java/com/example/util/simpletimetracker/core/base/BaseActivity.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import android.view.LayoutInflater
66
import androidx.appcompat.app.AppCompatActivity
77
import androidx.lifecycle.LiveData
88
import androidx.viewbinding.ViewBinding
9+
import com.example.util.simpletimetracker.core.extension.allowDiskRead
910
import com.example.util.simpletimetracker.core.extension.allowDiskWrite
1011
import com.example.util.simpletimetracker.core.manager.ThemeManager
1112
import com.example.util.simpletimetracker.core.provider.ContextProvider
@@ -26,7 +27,7 @@ abstract class BaseActivity<T : ViewBinding> : AppCompatActivity() {
2627
}
2728

2829
override fun onCreate(savedInstanceState: Bundle?) {
29-
super.onCreate(savedInstanceState)
30+
allowDiskRead { super.onCreate(savedInstanceState) }
3031
contextProvider.attach(this)
3132
themeManager.setTheme(this)
3233
_binding = inflater(layoutInflater)

core/src/main/java/com/example/util/simpletimetracker/core/base/BaseViewModel.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,16 @@ import androidx.lifecycle.viewModelScope
55
import kotlinx.coroutines.CoroutineScope
66
import kotlinx.coroutines.Job
77

8-
abstract class BaseViewModel : ViewModel(), ScopeHolder, Throttler {
8+
abstract class BaseViewModel :
9+
ViewModel(),
10+
ScopeHolder,
11+
Throttler,
12+
DelayLoadHandler {
913

1014
override var throttleJob: Job? = null
1115

16+
override var delayDataLoad: Boolean = true
17+
1218
override fun getScope(): CoroutineScope {
1319
return viewModelScope
1420
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.example.util.simpletimetracker.core.base
2+
3+
import com.example.util.simpletimetracker.core.utils.DELAY_DATA_LOAD_MS
4+
import kotlinx.coroutines.delay
5+
6+
interface DelayLoadHandler {
7+
8+
var delayDataLoad: Boolean
9+
10+
suspend fun delayLoad() {
11+
if (delayDataLoad) {
12+
// Delay data set on view to avoid screen open lag.
13+
delay(DELAY_DATA_LOAD_MS)
14+
delayDataLoad = false
15+
}
16+
}
17+
}

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

Lines changed: 34 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.example.util.simpletimetracker.domain.record.mapper.RangeMapper
55
import com.example.util.simpletimetracker.domain.record.model.Range
66
import com.example.util.simpletimetracker.domain.statistics.model.RangeLength
77
import com.example.util.simpletimetracker.domain.record.model.Record
8+
import com.example.util.simpletimetracker.domain.record.model.RecordBase
89
import com.example.util.simpletimetracker.domain.record.model.RunningRecord
910
import java.lang.Long.max
1011
import javax.inject.Inject
@@ -22,18 +23,6 @@ class GetCurrentRecordsDurationInteractor @Inject constructor(
2223
return getRangeCurrent(typeId, runningRecord, RangeLength.Day)
2324
}
2425

25-
suspend fun getDailyCurrent(runningRecord: RunningRecord): Result {
26-
return getRangeCurrent(runningRecord.id, runningRecord, RangeLength.Day)
27-
}
28-
29-
suspend fun getWeeklyCurrent(runningRecord: RunningRecord): Result {
30-
return getRangeCurrent(runningRecord.id, runningRecord, RangeLength.Week)
31-
}
32-
33-
suspend fun getMonthlyCurrent(runningRecord: RunningRecord): Result {
34-
return getRangeCurrent(runningRecord.id, runningRecord, RangeLength.Month)
35-
}
36-
3726
suspend fun getAllCurrents(
3827
typeIds: List<Long>,
3928
runningRecords: List<RunningRecord>,
@@ -48,8 +37,30 @@ class GetCurrentRecordsDurationInteractor @Inject constructor(
4837

4938
return typeIds.associateWith { typeId ->
5039
getRangeCurrent(
51-
filterRecords = { records -> records.filter { it.typeId == typeId } },
52-
runningRecords = runningRecords.filter { it.id == typeId },
40+
filter = { record -> typeId in record.typeIds },
41+
allRunningRecords = runningRecords,
42+
range = range,
43+
rangeRecords = rangeRecords,
44+
)
45+
}
46+
}
47+
48+
suspend fun getAllCategoryCurrents(
49+
recordTypeCategories: Map<Long, List<Long>>,
50+
runningRecords: List<RunningRecord>,
51+
rangeLength: RangeLength,
52+
): Map<Long, Result> {
53+
val range = getRange(rangeLength)
54+
val rangeRecords = getRangeRecords(
55+
rangeLength = rangeLength,
56+
range = range,
57+
typeIds = recordTypeCategories.values.flatten().distinct(),
58+
)
59+
60+
return recordTypeCategories.mapValues { (_, typeIds) ->
61+
getRangeCurrent(
62+
filter = { record -> record.typeIds.any { it in typeIds } },
63+
allRunningRecords = runningRecords,
5364
range = range,
5465
rangeRecords = rangeRecords,
5566
)
@@ -67,12 +78,8 @@ class GetCurrentRecordsDurationInteractor @Inject constructor(
6778

6879
return tagIds.associateWith { tagId ->
6980
getRangeCurrent(
70-
filterRecords = { records ->
71-
records.filter { record -> record.tags.any { it.tagId == tagId } }
72-
},
73-
runningRecords = runningRecords.filter { record ->
74-
record.tags.any { it.tagId in tagIds }
75-
},
81+
filter = { record -> record.tags.any { it.tagId == tagId } },
82+
allRunningRecords = runningRecords,
7683
range = range,
7784
rangeRecords = rangeRecords,
7885
)
@@ -90,22 +97,10 @@ class GetCurrentRecordsDurationInteractor @Inject constructor(
9097
)
9198
}
9299

93-
private suspend fun getRangeCurrent(
100+
suspend fun getRangeCurrent(
94101
typeId: Long,
95102
runningRecord: RunningRecord?,
96103
rangeLength: RangeLength,
97-
): Result {
98-
return getRangeCurrent(
99-
typeId = typeId,
100-
runningRecords = listOfNotNull(runningRecord),
101-
rangeLength = rangeLength,
102-
)
103-
}
104-
105-
private suspend fun getRangeCurrent(
106-
typeId: Long,
107-
runningRecords: List<RunningRecord>,
108-
rangeLength: RangeLength,
109104
): Result {
110105
val range = getRange(rangeLength)
111106
val rangeRecords = getRangeRecords(
@@ -115,19 +110,20 @@ class GetCurrentRecordsDurationInteractor @Inject constructor(
115110
)
116111

117112
return getRangeCurrent(
118-
filterRecords = { records -> records.filter { it.typeId == typeId } },
119-
runningRecords = runningRecords,
113+
filter = { record -> typeId in record.typeIds },
114+
allRunningRecords = listOfNotNull(runningRecord),
120115
range = range,
121116
rangeRecords = rangeRecords,
122117
)
123118
}
124119

125120
private fun getRangeCurrent(
126-
filterRecords: (List<Record>) -> List<Record>,
127-
runningRecords: List<RunningRecord>,
121+
filter: (RecordBase) -> Boolean,
122+
allRunningRecords: List<RunningRecord>,
128123
range: Range,
129124
rangeRecords: List<Record>,
130125
): Result {
126+
val runningRecords = allRunningRecords.filter(filter)
131127
val current = System.currentTimeMillis()
132128
val currentRunning = runningRecords.sumOf { runningRecord ->
133129
current - runningRecord.timeStarted
@@ -137,7 +133,7 @@ class GetCurrentRecordsDurationInteractor @Inject constructor(
137133
}
138134
val currentRunningCount = runningRecords.size
139135

140-
val records = filterRecords(rangeRecords)
136+
val records = rangeRecords.filter(filter)
141137
.map { rangeMapper.clampToRange(it, range) }
142138
val duration = records
143139
.let(rangeMapper::mapToDuration)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class GetRunningRecordViewDataMediator @Inject constructor(
2929
showSeconds: Boolean,
3030
): RunningRecordViewData {
3131
val dailyCurrent = if ((goals.getDaily() != null && goalsVisible) || totalDurationVisible) {
32-
getCurrentRecordsDurationInteractor.getDailyCurrent(record)
32+
getCurrentRecordsDurationInteractor.getDailyCurrent(typeId = record.id, runningRecord = record)
3333
} else {
3434
null
3535
}

core/src/main/java/com/example/util/simpletimetracker/core/sharedViewModel/RemoveRecordViewModel.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import com.example.util.simpletimetracker.domain.record.interactor.AddRecordMedi
1111
import com.example.util.simpletimetracker.domain.record.interactor.RecordInteractor
1212
import com.example.util.simpletimetracker.domain.record.interactor.RemoveRecordMediator
1313
import com.example.util.simpletimetracker.domain.record.model.Record
14+
import com.example.util.simpletimetracker.domain.record.model.RecordBase
1415
import com.example.util.simpletimetracker.domain.recordType.interactor.RecordTypeInteractor
1516
import com.example.util.simpletimetracker.navigation.params.notification.SnackBarParams
1617
import com.example.util.simpletimetracker.navigation.params.screen.ChangeRecordParams
@@ -45,8 +46,10 @@ class RemoveRecordViewModel @Inject constructor(
4546

4647
val typeIds = removedRecords.map(Record::typeId).distinct()
4748
removeRecordMediator.remove(
48-
recordIds = removedRecords.map { it.id },
49+
recordIds = removedRecords.map(Record::id),
4950
typeIds = typeIds,
51+
tagIds = removedRecords.map(Record::tags).flatten()
52+
.map(RecordBase.Tag::tagId).distinct(),
5053
)
5154

5255
val removedRecordsCount = removedRecords.size

core/src/main/java/com/example/util/simpletimetracker/core/utils/CoreConsts.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,6 @@ const val EXTRA_RECORD_COMMENT_MODE = "extra_record_comment_mode" // set, append
3333
const val EXTRA_FIND_RECORD_MODE = "extra_find_record_mode" // current_or_last, current, last
3434
const val EXTRA_FIND_RECORD_WITH_ACTIVITY_NAME = "extra_find_record_with_activity_name"
3535
const val EXTRA_GOAL_TYPE = "extra_goal_type" // duration, count
36-
const val EXTRA_GOAL_VALUE = "extra_goal_value"
36+
const val EXTRA_GOAL_VALUE = "extra_goal_value"
37+
38+
const val DELAY_DATA_LOAD_MS = 300L // Same as @integer/screen_animation_time

data_local/src/main/java/com/example/util/simpletimetracker/data_local/recordType/RecordTypeGoalDao.kt

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,27 +15,9 @@ interface RecordTypeGoalDao {
1515
@Query("SELECT * FROM recordTypeGoals WHERE id = :id LIMIT 1")
1616
suspend fun get(id: Long): RecordTypeGoalDBO?
1717

18-
@Query("SELECT * FROM recordTypeGoals WHERE owner_type == 0")
19-
suspend fun getAllTypeGoals(): List<RecordTypeGoalDBO>
20-
21-
@Query("SELECT * FROM recordTypeGoals WHERE owner_type == 1")
22-
suspend fun getAllCategoryGoals(): List<RecordTypeGoalDBO>
23-
24-
// TODO TAG GOAL remove owner_type checking, should not depend on it.
25-
@Query("SELECT * FROM recordTypeGoals WHERE owner_type == 2")
26-
suspend fun getAllTagGoals(): List<RecordTypeGoalDBO>
27-
28-
@Transaction
29-
@Query("SELECT * FROM recordTypeGoals WHERE owner_type == 0 AND owner_id = :typeId")
30-
suspend fun getByType(typeId: Long): List<RecordTypeGoalDBO>
31-
32-
@Transaction
33-
@Query("SELECT * FROM recordTypeGoals WHERE owner_type == 1 AND owner_id = :categoryId")
34-
suspend fun getByCategory(categoryId: Long): List<RecordTypeGoalDBO>
35-
3618
@Transaction
37-
@Query("SELECT * FROM recordTypeGoals WHERE owner_type == 2 AND owner_id = :tagId")
38-
suspend fun getByTag(tagId: Long): List<RecordTypeGoalDBO>
19+
@Query("SELECT * FROM recordTypeGoals WHERE owner_id = :ownerId")
20+
suspend fun getByOwnerId(ownerId: Long): List<RecordTypeGoalDBO>
3921

4022
@Insert(onConflict = OnConflictStrategy.REPLACE)
4123
suspend fun insert(recordTypeGoal: RecordTypeGoalDBO): Long

0 commit comments

Comments
 (0)