Skip to content

Commit 863f58b

Browse files
committed
add duplicate action to running record
1 parent 14b6986 commit 863f58b

10 files changed

Lines changed: 106 additions & 22 deletions

File tree

app/src/androidTest/java/com/example/util/simpletimetracker/RecordActionsDuplicateTest.kt

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import androidx.test.espresso.matcher.ViewMatchers.withText
1010
import androidx.test.ext.junit.runners.AndroidJUnit4
1111
import com.example.util.simpletimetracker.utils.BaseUiTest
1212
import com.example.util.simpletimetracker.utils.NavUtils
13-
import com.example.util.simpletimetracker.utils.checkViewDoesNotExist
1413
import com.example.util.simpletimetracker.utils.checkViewIsDisplayed
1514
import com.example.util.simpletimetracker.utils.clickOnRecyclerItem
1615
import com.example.util.simpletimetracker.utils.clickOnView
@@ -52,22 +51,34 @@ class RecordActionsDuplicateTest : BaseUiTest() {
5251
testUtils.addRunningRecord(name)
5352
Thread.sleep(1000)
5453

55-
// Running record - not shown
54+
// Running record - shown
5655
tryAction {
5756
longClickOnView(
58-
allOf(withId(baseR.id.viewRunningRecordItem), hasDescendant(withText(name)), isCompletelyDisplayed()),
57+
allOf(
58+
withId(baseR.id.viewRunningRecordItem),
59+
hasDescendant(withText(name)),
60+
isCompletelyDisplayed(),
61+
),
5962
)
6063
}
6164
onView(withText(coreR.string.change_record_actions_hint)).perform(nestedScrollTo())
6265
clickOnViewWithText(coreR.string.change_record_actions_hint)
63-
checkViewDoesNotExist(withText(coreR.string.change_record_duplicate))
66+
scrollRecyclerToView(
67+
changeRecordR.id.rvChangeRecordAction,
68+
hasDescendant(withText(coreR.string.change_record_duplicate)),
69+
)
70+
checkViewIsDisplayed(withText(coreR.string.change_record_duplicate))
6471
pressBack()
6572
pressBack()
6673

6774
// Record - shown
6875
NavUtils.openRecordsScreen()
6976
clickOnView(
70-
allOf(withId(baseR.id.viewRecordItem), hasDescendant(withText(name)), isCompletelyDisplayed()),
77+
allOf(
78+
withId(baseR.id.viewRecordItem),
79+
hasDescendant(withText(name)),
80+
isCompletelyDisplayed(),
81+
),
7182
)
7283
onView(withText(coreR.string.change_record_actions_hint)).perform(nestedScrollTo())
7384
clickOnViewWithText(coreR.string.change_record_actions_hint)
@@ -78,6 +89,55 @@ class RecordActionsDuplicateTest : BaseUiTest() {
7889
checkViewIsDisplayed(withText(coreR.string.change_record_duplicate))
7990
}
8091

92+
@Test
93+
fun duplicateRunningRecord() {
94+
val nameA = "NameA"
95+
val tag = "Tag"
96+
val comment = "Some_comment"
97+
val timeStarted = System.currentTimeMillis() - TimeUnit.MINUTES.toMillis(30)
98+
val timeStartedPreview = timeStarted.formatTime()
99+
val timeEndedPreview = System.currentTimeMillis().formatTime()
100+
val fullName = "$nameA - $tag"
101+
102+
// Setup
103+
testUtils.addActivity(nameA)
104+
testUtils.addRecordTag(tag, typeName = nameA)
105+
testUtils.addRunningRecord(
106+
typeName = nameA,
107+
timeStarted = timeStarted,
108+
tagNames = listOf(tag),
109+
comment = comment,
110+
)
111+
runBlocking { prefsInteractor.setAllowMultitasking(true) }
112+
113+
// Duplicate running to same type
114+
NavUtils.openRecordsScreen()
115+
longClickOnView(allOf(withText(fullName), isCompletelyDisplayed()))
116+
clickOnViewWithText(coreR.string.change_record_duplicate)
117+
118+
tryAction {
119+
checkViewIsDisplayed(
120+
allOf(
121+
withId(baseR.id.viewRunningRecordItem),
122+
hasDescendant(withText(fullName)),
123+
hasDescendant(withText(timeStartedPreview)),
124+
hasDescendant(withText(comment)),
125+
isCompletelyDisplayed(),
126+
),
127+
)
128+
checkViewIsDisplayed(
129+
allOf(
130+
withId(baseR.id.viewRecordItem),
131+
hasDescendant(withText(fullName)),
132+
hasDescendant(withText(timeStartedPreview)),
133+
hasDescendant(withText(timeEndedPreview)),
134+
hasDescendant(withText(comment)),
135+
isCompletelyDisplayed(),
136+
),
137+
)
138+
}
139+
}
140+
81141
@Test
82142
fun duplicateRecord() {
83143
val name = "Name"

app/src/androidTest/java/com/example/util/simpletimetracker/RecordQuickActionsTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ class RecordQuickActionsTest : BaseUiTest() {
100100
checkViewIsDisplayed(withText(R.string.archive_dialog_delete))
101101
checkViewDoesNotExist(withText(R.string.change_record_continue))
102102
checkViewDoesNotExist(withText(R.string.change_record_repeat))
103-
checkViewDoesNotExist(withText(R.string.change_record_duplicate))
103+
checkViewIsDisplayed(withText(R.string.change_record_duplicate))
104104
checkViewDoesNotExist(withText(R.string.change_record_move))
105105
checkViewIsDisplayed(withText(R.string.change_record_multiselect))
106106
checkViewIsDisplayed(withText(R.string.data_edit_change_activity))

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ abstract class ChangeRecordBaseViewModel(
134134
protected abstract val adjustNextRecordAvailable: Boolean
135135
protected abstract val isTimeEndedAvailable: Boolean
136136
protected abstract val isAdditionalActionsAvailable: Boolean
137+
protected abstract val isDuplicateActionAvailable: Boolean
137138
protected abstract val isDeleteButtonVisible: Boolean
138139
protected abstract val isStatisticsButtonVisible: Boolean
139140

@@ -813,7 +814,8 @@ abstract class ChangeRecordBaseViewModel(
813814
showTimeEndedOnSplitPreview = showTimeEndedOnSplitPreview,
814815
),
815816
duplicateParams = ViewDataParams.DuplicateParams(
816-
isAvailable = isAdditionalActionsAvailable,
817+
isAvailable = isDuplicateActionAvailable,
818+
newTimeEnded = previewTimeEnded,
817819
),
818820
moveParams = ViewDataParams.MoveParams(
819821
isAvailable = isAdditionalActionsAvailable,

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ class ChangeRecordViewModel @Inject constructor(
8383
override val adjustNextRecordAvailable: Boolean get() = true
8484
override val isTimeEndedAvailable: Boolean get() = true
8585
override val isAdditionalActionsAvailable: Boolean get() = true
86+
override val isDuplicateActionAvailable: Boolean get() = true
8687
override val isDeleteButtonVisible: Boolean get() = recordId.orZero() != 0L
8788
override val isStatisticsButtonVisible: Boolean
8889
get() = extra is ChangeRecordParams.Tracked ||

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class ChangeRecordDelegateBridge(
6666

6767
data class DuplicateParams(
6868
val isAvailable: Boolean,
69+
val newTimeEnded: Long,
6970
)
7071

7172
data class MoveParams(

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class ChangeRecordActionsDuplicateDelegate @Inject constructor(
4040
recordActionDuplicateMediator.execute(
4141
typeId = params.baseParams.newTypeId,
4242
timeStarted = params.baseParams.newTimeStarted,
43-
timeEnded = params.baseParams.newTimeEnded,
43+
timeEnded = params.duplicateParams.newTimeEnded,
4444
comment = params.baseParams.newComment,
4545
tagIds = params.baseParams.newTags,
4646
)

features/feature_change_running_record/src/main/java/com/example/util/simpletimetracker/feature_change_running_record/viewModel/ChangeRunningRecordViewModel.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ class ChangeRunningRecordViewModel @Inject constructor(
9595
override val showTimeEndedOnAdjustPreview: Boolean get() = false
9696
override val isTimeEndedAvailable: Boolean get() = false
9797
override val isAdditionalActionsAvailable: Boolean get() = false
98+
override val isDuplicateActionAvailable: Boolean get() = true
9899
override val isDeleteButtonVisible: Boolean get() = true
99100
override val isStatisticsButtonVisible: Boolean get() = true
100101

features/feature_dialogs/src/main/java/com/example/util/simpletimetracker/feature_dialogs/recordQuickActions/interactor/RecordQuickActionsViewDataInteractor.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ class RecordQuickActionsViewDataInteractor @Inject constructor(
228228
is Type.RecordRunning -> listOfNotNull(
229229
RecordQuickActionsButton.STATISTICS,
230230
RecordQuickActionsButton.DELETE,
231+
RecordQuickActionsButton.DUPLICATE,
231232
RecordQuickActionsButton.STOP,
232233
RecordQuickActionsButton.MULTISELECT,
233234
RecordQuickActionsButton.CHANGE_ACTIVITY,

features/feature_dialogs/src/main/java/com/example/util/simpletimetracker/feature_dialogs/recordQuickActions/viewModel/RecordQuickActionsViewModel.kt

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import com.example.util.simpletimetracker.core.extension.toViewData
1010
import com.example.util.simpletimetracker.core.interactor.StatisticsDetailNavigationInteractor
1111
import com.example.util.simpletimetracker.core.repo.ResourceRepo
1212
import com.example.util.simpletimetracker.domain.base.UNTRACKED_ITEM_ID
13-
import com.example.util.simpletimetracker.domain.extension.orZero
1413
import com.example.util.simpletimetracker.domain.prefs.interactor.PrefsInteractor
1514
import com.example.util.simpletimetracker.domain.record.interactor.RecordInteractor
1615
import com.example.util.simpletimetracker.domain.record.interactor.RecordsContainerMultiselectInteractor
@@ -146,7 +145,7 @@ class RecordQuickActionsViewModel @Inject constructor(
146145
when (val params = extra.type) {
147146
is Type.RecordTracked -> {
148147
// Removal handled in separate viewModel.
149-
val recordId = (params as? Type.RecordTracked)?.id.orZero()
148+
val recordId = params.id
150149
removeRecordIds.set(setOf(recordId))
151150
router.back()
152151
}
@@ -206,15 +205,35 @@ class RecordQuickActionsViewModel @Inject constructor(
206205
exit()
207206
return
208207
}
209-
val record = getTrackedRecord() ?: return
210-
recordActionDuplicateMediator.execute(
211-
typeId = record.typeId,
212-
timeStarted = record.timeStarted,
213-
timeEnded = record.timeEnded,
214-
comment = record.comment,
215-
tagIds = record.tags,
216-
)
217-
exit()
208+
when (extra.type) {
209+
is Type.RecordTracked -> {
210+
val record = getTrackedRecord() ?: return
211+
recordActionDuplicateMediator.execute(
212+
typeId = record.typeId,
213+
timeStarted = record.timeStarted,
214+
timeEnded = record.timeEnded,
215+
comment = record.comment,
216+
tagIds = record.tags,
217+
)
218+
exit()
219+
}
220+
is Type.RecordUntracked -> {
221+
// Do nothing, shouldn't be possible.
222+
}
223+
is Type.RecordRunning -> {
224+
val record = (extra.type as? Type.RecordRunning)
225+
?.let { runningRecordInteractor.get(it.id) }
226+
?: return
227+
recordActionDuplicateMediator.execute(
228+
typeId = record.id,
229+
timeStarted = record.timeStarted,
230+
timeEnded = record.timeEnded,
231+
comment = record.comment,
232+
tagIds = record.tags,
233+
)
234+
exit()
235+
}
236+
}
218237
}
219238

220239
private suspend fun onMove() {
@@ -375,8 +394,7 @@ class RecordQuickActionsViewModel @Inject constructor(
375394
}
376395

377396
private suspend fun getTrackedRecord(): Record? {
378-
val recordId = (extra.type as? Type.RecordTracked)?.id
379-
?: return null
397+
val recordId = (extra.type as? Type.RecordTracked)?.id ?: return null
380398
return recordInteractor.get(recordId)
381399
}
382400

features/feature_records/src/main/java/com/example/util/simpletimetracker/feature_records/interactor/RecordsViewDataInteractor.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ class RecordsViewDataInteractor @Inject constructor(
398398
}
399399

400400
return filterRecords(
401-
records = trackedRecordsData + runningRecordsData,
401+
records = runningRecordsData + trackedRecordsData, // Timers should be first for correct sort.
402402
chartFilterType = filterType,
403403
filteredIds = filteredIds,
404404
lazyRecordTypeCategories = recordTypeCategories,

0 commit comments

Comments
 (0)