Skip to content

Commit

Permalink
refactor: move search to fab (#1138)
Browse files Browse the repository at this point in the history
* feat: add fab on series screen for search

* refactor: remove search from the bottom nav

* refactor: rename host screen to search

* fix: hide the bottom bar on search screen

* test: update tests for path to search screen

* refactor: move content description to strings file

* feat: hide or show the fab based on scrolling

* feat: add extra padding to bottom of collection view

Add extra padding so the fab cannot get stuck in the way of the +1 buttons on cards.

* refactor: switch to use the expanded fab

* style: ktlint fix

* test: remove top level test to navigate to search
  • Loading branch information
Chesire authored Dec 2, 2023
1 parent a2d7553 commit 5bbbd2b
Show file tree
Hide file tree
Showing 32 changed files with 263 additions and 165 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,6 @@ class ActivityTests : UITest() {
}
}

@Test
fun overviewCanNavigateToSearchView() {
launchActivity()

activity(composeTestRule) {
goToSearch()
validate {
isOnSearchScreen()
}
}
}

@Test
fun overviewCanNavigateToSettingsView() {
launchActivity()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import com.chesire.nekome.UITest
import com.chesire.nekome.core.models.ErrorDomain
import com.chesire.nekome.datasource.search.remote.SearchApi
import com.chesire.nekome.robots.activity
import com.chesire.nekome.robots.search.host
import com.chesire.nekome.robots.search.search
import com.chesire.nekome.robots.series.seriesList
import com.github.michaelbull.result.Err
import com.github.michaelbull.result.Ok
import dagger.hilt.android.testing.HiltAndroidTest
Expand Down Expand Up @@ -41,9 +42,12 @@ class SearchTests : UITest() {
launchActivity()

activity(composeTestRule) {
goToAnime()
}
seriesList(composeTestRule) {
goToSearch()
}
host(composeTestRule) {
search(composeTestRule) {
validate { isVisible() }
}
}
Expand All @@ -53,9 +57,12 @@ class SearchTests : UITest() {
launchActivity()

activity(composeTestRule) {
goToAnime()
}
seriesList(composeTestRule) {
goToSearch()
}
host(composeTestRule) {
search(composeTestRule) {
searchTerm("")
selectAnime()
clickSearch()
Expand All @@ -69,9 +76,12 @@ class SearchTests : UITest() {
launchActivity()

activity(composeTestRule) {
goToAnime()
}
seriesList(composeTestRule) {
goToSearch()
}
host(composeTestRule) {
search(composeTestRule) {
searchTerm(GENERIC_ERROR)
selectAnime()
clickSearch()
Expand All @@ -85,9 +95,12 @@ class SearchTests : UITest() {
launchActivity()

activity(composeTestRule) {
goToAnime()
}
seriesList(composeTestRule) {
goToSearch()
}
host(composeTestRule) {
search(composeTestRule) {
searchTerm(NO_RESULTS_ERROR)
selectAnime()
clickSearch()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,27 @@ import androidx.compose.ui.test.onChild
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextInput
import com.chesire.nekome.app.search.host.ui.HostTags
import com.chesire.nekome.app.search.search.ui.SearchTags

/**
* Method to interact with the [HostRobot].
* Method to interact with the [SearchRobot].
*/
fun host(
fun search(
composeContentTestRule: ComposeContentTestRule,
func: HostRobot.() -> Unit
) = HostRobot(composeContentTestRule).apply(func)
func: SearchRobot.() -> Unit
) = SearchRobot(composeContentTestRule).apply(func)

/**
* Robot to interact with the search host screen.
*/
class HostRobot(private val composeContentTestRule: ComposeContentTestRule) {
class SearchRobot(private val composeContentTestRule: ComposeContentTestRule) {

/**
* Enters the term to search for.
*/
fun searchTerm(term: String) {
composeContentTestRule
.onNodeWithTag(HostTags.Input)
.onNodeWithTag(SearchTags.Input)
.performTextInput(term)
}

Expand All @@ -36,7 +36,7 @@ class HostRobot(private val composeContentTestRule: ComposeContentTestRule) {
*/
fun selectAnime() {
composeContentTestRule
.onNodeWithTag(HostTags.Anime)
.onNodeWithTag(SearchTags.Anime)
.performClick()
}

Expand All @@ -45,7 +45,7 @@ class HostRobot(private val composeContentTestRule: ComposeContentTestRule) {
*/
fun selectManga() {
composeContentTestRule
.onNodeWithTag(HostTags.Manga)
.onNodeWithTag(SearchTags.Manga)
.performClick()
}

Expand All @@ -54,28 +54,28 @@ class HostRobot(private val composeContentTestRule: ComposeContentTestRule) {
*/
fun clickSearch() {
composeContentTestRule
.onNodeWithTag(HostTags.Search)
.onNodeWithTag(SearchTags.Search)
.performClick()
}

/**
* Executes validation steps.
*/
infix fun validate(func: HostResultRobot.() -> Unit) =
HostResultRobot(composeContentTestRule).apply(func)
infix fun validate(func: SearchResultRobot.() -> Unit) =
SearchResultRobot(composeContentTestRule).apply(func)
}

/**
* Robot to check the results for the search screen.
*/
class HostResultRobot(private val composeContentTestRule: ComposeContentTestRule) {
class SearchResultRobot(private val composeContentTestRule: ComposeContentTestRule) {

/**
* Asserts the search screen is shown.
*/
fun isVisible() {
composeContentTestRule
.onNodeWithTag(HostTags.Root)
.onNodeWithTag(SearchTags.Root)
.assertIsDisplayed()
}

Expand All @@ -84,7 +84,7 @@ class HostResultRobot(private val composeContentTestRule: ComposeContentTestRule
*/
fun isEmptySearchError() {
composeContentTestRule
.onNodeWithTag(HostTags.Snackbar)
.onNodeWithTag(SearchTags.Snackbar)
.assertIsDisplayed()
.onChild()
.onChild()
Expand All @@ -101,7 +101,7 @@ class HostResultRobot(private val composeContentTestRule: ComposeContentTestRule
*/
fun isGenericError() {
composeContentTestRule
.onNodeWithTag(HostTags.Snackbar)
.onNodeWithTag(SearchTags.Snackbar)
.assertIsDisplayed()
.onChild()
.onChild()
Expand All @@ -118,7 +118,7 @@ class HostResultRobot(private val composeContentTestRule: ComposeContentTestRule
*/
fun isNoSeriesFoundError() {
composeContentTestRule
.onNodeWithTag(HostTags.Snackbar)
.onNodeWithTag(SearchTags.Snackbar)
.assertIsDisplayed()
.onChild()
.onChild()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ class SeriesListRobot(private val composeContentTestRule: ComposeContentTestRule
}
}

/**
* Presses the search button.
*/
fun goToSearch() {
composeContentTestRule
.onNodeWithTag(SeriesCollectionTags.SearchFab)
.performClick()
}

/**
* Presses the increment watched button on the series at position [itemPosition].
*/
Expand Down
29 changes: 19 additions & 10 deletions app/src/main/java/com/chesire/nekome/ui/Routes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import androidx.navigation.NavHostController
import androidx.navigation.compose.composable
import com.chesire.nekome.app.login.credentials.ui.CredentialsScreen
import com.chesire.nekome.app.login.syncing.ui.SyncingScreen
import com.chesire.nekome.app.search.host.ui.HostScreen
import com.chesire.nekome.app.search.search.ui.SearchScreen
import com.chesire.nekome.app.series.collection.ui.CollectionScreen
import com.chesire.nekome.app.series.item.ui.ItemScreen
import com.chesire.nekome.app.settings.config.ui.ConfigScreen
Expand All @@ -17,7 +17,6 @@ import com.chesire.nekome.app.settings.oss.ui.OssScreen
val bottomNavRoutes = listOf<BottomNavTarget>(
Screen.Anime,
Screen.Manga,
Screen.Host,
Screen.Config
)

Expand All @@ -43,18 +42,28 @@ fun NavGraphBuilder.addSeriesRoutes(navController: NavHostController) {
route = Screen.Anime.route,
arguments = Screen.Anime.args
) {
CollectionScreen { seriesId, seriesTitle ->
navController.navigate("${Screen.Item.destination}/$seriesId/$seriesTitle")
}
CollectionScreen(
navigateToItem = { seriesId, seriesTitle ->
navController.navigate("${Screen.Item.destination}/$seriesId/$seriesTitle")
},
navigateToSearch = {
navController.navigate(Screen.Search.route)
}
)
}

composable(
route = Screen.Manga.route,
arguments = Screen.Manga.args
) {
CollectionScreen { seriesId, seriesTitle ->
navController.navigate("${Screen.Item.destination}/$seriesId/$seriesTitle")
}
CollectionScreen(
navigateToItem = { seriesId, seriesTitle ->
navController.navigate("${Screen.Item.destination}/$seriesId/$seriesTitle")
},
navigateToSearch = {
navController.navigate(Screen.Search.route)
}
)
}

composable(
Expand All @@ -66,8 +75,8 @@ fun NavGraphBuilder.addSeriesRoutes(navController: NavHostController) {
}

fun NavGraphBuilder.addSearchRoutes() {
composable(Screen.Host.route) {
HostScreen()
composable(Screen.Search.route) {
SearchScreen()
}
}

Expand Down
18 changes: 7 additions & 11 deletions app/src/main/java/com/chesire/nekome/ui/Screen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package com.chesire.nekome.ui
import androidx.annotation.StringRes
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.CollectionsBookmark
import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material.icons.filled.VideoLibrary
import androidx.compose.ui.graphics.vector.ImageVector
Expand All @@ -23,32 +22,29 @@ sealed class Screen {
return when (route) {
Anime.route,
Manga.route,
Host.route,
Config.route -> true

Credentials.route,
Item.route,
OSS.route,
Search.route,
Syncing.route -> false

else -> false
}
}
}

object Credentials : Screen() {
data object Credentials : Screen() {
override val route = "credentials"
}

object Syncing : Screen() {
data object Syncing : Screen() {
override val route = "syncing"
}

object Host : Screen(), BottomNavTarget {
override val route = "host"
override val title = StringResource.nav_search
override val icon = Icons.Default.Search
override val tag = MainActivityTags.Search
data object Search : Screen() {
override val route = "search"
}

object Anime : Screen(), BottomNavTarget {
Expand Down Expand Up @@ -81,7 +77,7 @@ sealed class Screen {
override val tag = MainActivityTags.Manga
}

object Item : Screen() {
data object Item : Screen() {
override val route = "item/{seriesId}/{seriesTitle}"
const val destination = "item"

Expand All @@ -98,7 +94,7 @@ sealed class Screen {
override val tag = MainActivityTags.Settings
}

object OSS : Screen() {
data object OSS : Screen() {
override val route = "oss"
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.chesire.nekome.core.compose

import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue

/**
* Returns whether the lazy list is currently scrolling up.
*/
@Composable
fun LazyListState.isScrollingUp(): Boolean {
var previousIndex by remember(this) { mutableIntStateOf(firstVisibleItemIndex) }
var previousScrollOffset by remember(this) { mutableIntStateOf(firstVisibleItemScrollOffset) }
return remember(this) {
derivedStateOf {
if (previousIndex != firstVisibleItemIndex) {
previousIndex > firstVisibleItemIndex
} else {
previousScrollOffset >= firstVisibleItemScrollOffset
}.also {
previousIndex = firstVisibleItemIndex
previousScrollOffset = firstVisibleItemScrollOffset
}
}
}.value
}
2 changes: 2 additions & 0 deletions core/resources/src/main/res/values-ja/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@
<string name="series_list_empty">現在のフィルターで見つかったシリーズはありません</string>
<string name="series_list_refresh">リフレッシュシリーズ</string>
<string name="series_list_refresh_error">シリーズ一覧を更新する際にエラーが発生しました。もう一度やり直してください…</string>
<string name="series_list_search_fab_text">新しく追加する</string>
<string name="series_list_search_content_description">追加する新しいシリーズを検索します</string>
<string name="rate_dialog_title">レートシリーズ</string>
<string name="series_list_rate_cancel">キャンセル</string>
<string name="series_list_rate_confirm">確認</string>
Expand Down
2 changes: 2 additions & 0 deletions core/resources/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@
<string name="series_list_empty">No series found with the current filter</string>
<string name="series_list_refresh">Refresh series</string>
<string name="series_list_refresh_error">Encountered error trying to refresh series list, please try again…</string>
<string name="series_list_search_fab_text">Add new</string>
<string name="series_list_search_content_description">Search for new series to add</string>
<string name="rate_dialog_title">Rate Series</string>
<string name="series_list_rate_cancel">Cancel</string>
<string name="series_list_rate_confirm">Confirm</string>
Expand Down
Loading

0 comments on commit 5bbbd2b

Please sign in to comment.