feat: add board detail create and filter toolbar UI

This commit is contained in:
2026-03-16 14:47:31 -04:00
parent de7bb48fe2
commit b936baf564
12 changed files with 596 additions and 16 deletions

View File

@@ -27,6 +27,7 @@ import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.color.MaterialColors
import com.google.android.material.chip.Chip
import java.text.DateFormat
import java.time.LocalDate
import java.util.ArrayDeque
import java.util.Date
import java.util.Locale
@@ -50,6 +51,7 @@ import space.hackenslacker.kanbn4droid.app.boarddetail.BoardDetailDataSource
import space.hackenslacker.kanbn4droid.app.boarddetail.BoardListDetail
import space.hackenslacker.kanbn4droid.app.boarddetail.BoardTagSummary
import space.hackenslacker.kanbn4droid.app.boarddetail.CardBatchMutationResult
import space.hackenslacker.kanbn4droid.app.boarddetail.CreatedEntityRef
import space.hackenslacker.kanbn4droid.app.auth.ApiKeyStore
import space.hackenslacker.kanbn4droid.app.auth.SessionStore
import space.hackenslacker.kanbn4droid.app.boards.BoardsApiResult
@@ -307,6 +309,54 @@ class BoardDetailFlowTest {
}
}
@Test
fun toolbarNormalMode_showsFilterAndSearchActions() {
val scenario = launchBoardDetail()
onView(withText("Card 1")).check(matches(isDisplayed()))
awaitCondition {
var present = false
scenario.onActivity { activity ->
val menu = activity.findViewById<com.google.android.material.appbar.MaterialToolbar>(R.id.boardDetailToolbar).menu
present = menu.findItem(R.id.actionFilterByTag) != null && menu.findItem(R.id.actionSearch) != null
}
present
}
scenario.onActivity { activity ->
val menu = activity.findViewById<com.google.android.material.appbar.MaterialToolbar>(R.id.boardDetailToolbar).menu
assertNotNull(menu.findItem(R.id.actionFilterByTag))
assertNotNull(menu.findItem(R.id.actionSearch))
}
}
@Test
fun selectionMode_replacesFilterSearchWithSelectionActions() {
val scenario = launchBoardDetail()
onView(withText("Card 1")).perform(longClick())
scenario.onActivity { activity ->
val menu = activity.findViewById<com.google.android.material.appbar.MaterialToolbar>(R.id.boardDetailToolbar).menu
assertNotNull(menu.findItem(R.id.actionSelectAll))
assertNotNull(menu.findItem(R.id.actionMoveCards))
assertNotNull(menu.findItem(R.id.actionDeleteCards))
assertNull(menu.findItem(R.id.actionFilterByTag))
assertNull(menu.findItem(R.id.actionSearch))
}
}
@Test
fun fab_isVisible_andOpensAddChooser() {
launchBoardDetail()
onView(withId(R.id.boardDetailCreateFab)).check(matches(isDisplayed()))
onView(withId(R.id.boardDetailCreateFab)).perform(click())
onView(withText("Add new list")).inRoot(isDialog()).check(matches(isDisplayed()))
onView(withText("Add new card")).inRoot(isDialog()).check(matches(isDisplayed()))
}
@Test
fun missingBoardIdShowsBlockingDialogAndFinishes() {
val scenario = launchBoardDetail(boardId = null)
@@ -636,6 +686,20 @@ class BoardDetailFlowTest {
var lastDeleteCardIds: Set<String> = emptySet()
var lastMoveTargetListId: String? = null
override suspend fun createList(boardPublicId: String, title: String): BoardsApiResult<CreatedEntityRef> {
return BoardsApiResult.Failure("Not implemented in test fake")
}
override suspend fun createCard(
listPublicId: String,
title: String,
description: String?,
dueDate: LocalDate?,
tagPublicIds: Collection<String>,
): BoardsApiResult<CreatedEntityRef> {
return BoardsApiResult.Failure("Not implemented in test fake")
}
override suspend fun getBoardDetail(boardId: String): BoardsApiResult<BoardDetail> {
loadGate?.await()
return if (loadResults.isNotEmpty()) {