Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Proposal] ♻️ Added the ability to go to the floor map from the session details. #1127

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -110,6 +110,9 @@ private fun KaigiNavHost(
onTimetableItemClick = navController::navigateToTimetableItemDetailScreen,
onNavigateToBookmarkScreenRequested = navController::navigateToBookmarkScreen,
onLinkClick = externalNavController::navigate,
onRoomClick = {
navController.popBackStack(navController.graph.startDestinationId, false)
Copy link
Member

@takahirom takahirom Sep 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it's difficult to think but what if we create navController::navigateToMainFloorMapScreen?
I think we can see parent navController to access getBackStackEntry 👀

Copy link
Contributor Author

@Corvus400 Corvus400 Sep 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once I was able to return to the start destination with the following code.

fun NavController.navigateToMainFloorMapScreen() {
    getBackStackEntry(timetableItemDetailScreenRoute).destination.parent?.startDestinationId?.let {
        navigate(it)
        // TODO navigateMainFloorMap
    }
}

However, I have not figured out how to move to FloorMapScreen from here without having to make any major changes.
Do you already have any ideas? 🙇

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about this. But I think we can pass the route parameter to NavHost and we may be able to pass /main/floorMap.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@takahirom
I have tried the suggested method, but unfortunately the app crashes. 🙇
We still think that as long as NavHost is split into two, it is unfortunately difficult to achieve this functionality other than this current implementation. 🙇

},
onCalendarRegistrationClick = externalNavController::navigateToCalendarRegistration,
onShareClick = externalNavController::onShareClick,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.github.droidkaigi.confsched2023.data.navigation

import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import io.github.droidkaigi.confsched2023.model.NavigationRequester
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import javax.inject.Singleton

@InstallIn(SingletonComponent::class)
@Module
class NavigationModule {
@Provides
@Singleton
fun provideNavigationRequester(): NavigationRequester = DefaultNavigationRequester()
}

class DefaultNavigationRequester : NavigationRequester {
private val _navigateRequestStateFlow = MutableStateFlow("")
override fun getNavigationRouteFlow(): Flow<String> = _navigateRequestStateFlow

override fun navigateTo(route: String) {
_navigateRequestStateFlow.value = route
}

override fun navigated() {
_navigateRequestStateFlow.value = ""
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.github.droidkaigi.confsched2023.model

import kotlinx.coroutines.flow.Flow

interface NavigationRequester {
fun getNavigationRouteFlow(): Flow<String>
fun navigateTo(route: String)
fun navigated()
}
Original file line number Diff line number Diff line change
@@ -43,6 +43,7 @@ class TimetableItemDetailScreenRobot @Inject constructor(
TimetableItemDetailScreen(
onNavigationIconClick = { },
onLinkClick = { },
onRoomClick = { },
onCalendarRegistrationClick = { },
onShareClick = { },
onNavigateToBookmarkScreenRequested = { },
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@ import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
@@ -108,6 +109,7 @@ fun MainScreen(
navigationType = navigationType,
routeToTab = mainNestedGraphStateHolder::routeToTab,
onTabSelected = mainNestedGraphStateHolder::onTabSelected,
onNavigated = viewModel::onNavigated,
mainNestedNavGraph = mainNestedNavGraph,
)
}
@@ -152,6 +154,7 @@ enum class MainScreenTab(

data class MainScreenUiState(
val isAchievementsEnabled: Boolean = false,
val navigationRoute: String,
)

@Composable
@@ -161,11 +164,18 @@ private fun MainScreen(
navigationType: NavigationType,
routeToTab: String.() -> MainScreenTab?,
onTabSelected: (NavController, MainScreenTab) -> Unit,
onNavigated: () -> Unit,
mainNestedNavGraph: NavGraphBuilder.(NavController, PaddingValues) -> Unit,
) {
val mainNestedNavController = rememberNavController()
val navBackStackEntry by mainNestedNavController.currentBackStackEntryAsState()
val currentTab = navBackStackEntry?.destination?.route?.routeToTab()
LaunchedEffect(uiState.navigationRoute) {
if (uiState.navigationRoute.isNotBlank()) {
mainNestedNavController.navigate(uiState.navigationRoute)
onNavigated()
}
}
Row(modifier = Modifier.fillMaxSize()) {
AnimatedVisibility(visible = navigationType == NAVIGATION_RAIL) {
KaigiNavigationRail(
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import io.github.droidkaigi.confsched2023.data.contributors.AchievementRepository
import io.github.droidkaigi.confsched2023.designsystem.strings.AppStrings
import io.github.droidkaigi.confsched2023.model.NavigationRequester
import io.github.droidkaigi.confsched2023.ui.UserMessageStateHolder
import io.github.droidkaigi.confsched2023.ui.buildUiState
import io.github.droidkaigi.confsched2023.ui.handleErrorAndRetry
@@ -16,6 +17,7 @@ import javax.inject.Inject
@HiltViewModel
class MainScreenViewModel @Inject constructor(
val userMessageStateHolder: UserMessageStateHolder,
private val navigationRequester: NavigationRequester,
achievementRepository: AchievementRepository,
) : ViewModel(),
UserMessageStateHolder by userMessageStateHolder {
@@ -30,11 +32,24 @@ class MainScreenViewModel @Inject constructor(
initialValue = false,
)

private val navigationRouteStateFlow: StateFlow<String> = navigationRequester.getNavigationRouteFlow()
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = "",
)

val uiState: StateFlow<MainScreenUiState> = buildUiState(
isAchievementsEnabledStateFlow,
) { isAchievementsEnabled ->
navigationRouteStateFlow,
) { isAchievementsEnabled, navigationRoute ->
MainScreenUiState(
isAchievementsEnabled = isAchievementsEnabled,
navigationRoute = navigationRoute,
)
}

fun onNavigated() {
navigationRequester.navigated()
}
}
Original file line number Diff line number Diff line change
@@ -49,13 +49,15 @@ fun NavGraphBuilder.sessionScreens(
onTimetableItemClick: (TimetableItem) -> Unit,
onNavigateToBookmarkScreenRequested: () -> Unit,
onLinkClick: (url: String) -> Unit,
onRoomClick: () -> Unit,
onCalendarRegistrationClick: (TimetableItem) -> Unit,
onShareClick: (TimetableItem) -> Unit,
) {
composable(timetableItemDetailScreenRoute) {
TimetableItemDetailScreen(
onNavigationIconClick = onNavigationIconClick,
onLinkClick = onLinkClick,
onRoomClick = onRoomClick,
onCalendarRegistrationClick = onCalendarRegistrationClick,
onNavigateToBookmarkScreenRequested = onNavigateToBookmarkScreenRequested,
onShareClick = onShareClick,
@@ -84,6 +86,7 @@ fun NavController.navigateToTimetableItemDetailScreen(
fun TimetableItemDetailScreen(
onNavigationIconClick: () -> Unit,
onLinkClick: (url: String) -> Unit,
onRoomClick: () -> Unit,
onCalendarRegistrationClick: (TimetableItem) -> Unit,
onNavigateToBookmarkScreenRequested: () -> Unit,
onShareClick: (TimetableItem) -> Unit,
@@ -109,6 +112,10 @@ fun TimetableItemDetailScreen(
onNavigationIconClick = onNavigationIconClick,
onBookmarkClick = viewModel::onBookmarkClick,
onLinkClick = onLinkClick,
onRoomClick = {
viewModel.navigateTo("floorMap")
Copy link
Contributor Author

@Corvus400 Corvus400 Sep 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to change this part if possible since it is directly specified.
It would be helpful if FloorMapScreenRoute could be referenced in this case.

onRoomClick()
},
onCalendarRegistrationClick = onCalendarRegistrationClick,
onShareClick = onShareClick,
onSelectedLanguage = viewModel::onSelectDescriptionLanguage,
@@ -145,6 +152,7 @@ private fun TimetableItemDetailScreen(
onLinkClick: (url: String) -> Unit,
onCalendarRegistrationClick: (TimetableItem) -> Unit,
onShareClick: (TimetableItem) -> Unit,
onRoomClick: () -> Unit,
onSelectedLanguage: (Lang) -> Unit,
snackbarHostState: SnackbarHostState,
) {
@@ -194,6 +202,7 @@ private fun TimetableItemDetailScreen(
uiState = it.timetableItemDetailSectionUiState,
selectedLanguage = it.currentLang,
onLinkClick = onLinkClick,
onRoomClick = onRoomClick,
contentPadding = innerPadding,
)
}
@@ -214,7 +223,9 @@ fun TimetableItemDetailScreenPreview() {
TimetableItemDetailScreen(
uiState = Loaded(
timetableItem = fakeSession,
timetableItemDetailSectionUiState = TimetableItemDetailSectionUiState(fakeSession),
timetableItemDetailSectionUiState = TimetableItemDetailSectionUiState(
fakeSession,
),
isBookmarked = isBookMarked,
isLangSelectable = true,
viewBookmarkListRequestState = ViewBookmarkListRequestState.NotRequested,
@@ -225,6 +236,7 @@ fun TimetableItemDetailScreenPreview() {
isBookMarked = !isBookMarked
},
onLinkClick = {},
onRoomClick = {},
onCalendarRegistrationClick = {},
onShareClick = {},
onSelectedLanguage = {},
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import io.github.droidkaigi.confsched2023.designsystem.strings.AppStrings
import io.github.droidkaigi.confsched2023.model.Lang
import io.github.droidkaigi.confsched2023.model.NavigationRequester
import io.github.droidkaigi.confsched2023.model.SessionsRepository
import io.github.droidkaigi.confsched2023.model.TimetableItem
import io.github.droidkaigi.confsched2023.model.TimetableItemId
@@ -29,6 +30,7 @@ import javax.inject.Inject
@HiltViewModel
class TimetableItemDetailViewModel @Inject constructor(
private val sessionsRepository: SessionsRepository,
private val navigationRequester: NavigationRequester,
val userMessageStateHolder: UserMessageStateHolder,
savedStateHandle: SavedStateHandle,
) : ViewModel(),
@@ -108,4 +110,10 @@ class TimetableItemDetailViewModel @Inject constructor(
) {
selectedDescriptionLanguageStateFlow.value = language
}

fun navigateTo(
route: String,
) {
navigationRequester.navigateTo(route)
}
}
Original file line number Diff line number Diff line change
@@ -40,6 +40,7 @@ import java.util.Locale
@Composable
fun TimetableItemDetailSummaryCard(
timetableItem: TimetableItem,
onRoomClick: () -> Unit,
modifier: Modifier = Modifier,
) {
Column(modifier = modifier) {
@@ -88,6 +89,7 @@ fun TimetableItemDetailSummaryCard(
leadingIcon = Icons.Outlined.Place,
label = SessionsStrings.Place.asString(),
content = timetableItem.room.nameAndFloor,
onContentClick = onRoomClick,
)
TimetableItemDetailSummaryCardRow(
leadingIcon = Icons.Outlined.Language,
@@ -110,7 +112,10 @@ fun TimetableItemDetailSummaryCard(
fun TimetableItemDetailSummaryPreview() {
KaigiTheme {
Surface {
TimetableItemDetailSummaryCard(timetableItem = Session.fake())
TimetableItemDetailSummaryCard(
timetableItem = Session.fake(),
onRoomClick = {},
)
}
}
}
Original file line number Diff line number Diff line change
@@ -16,9 +16,13 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import io.github.droidkaigi.confsched2023.designsystem.component.ClickableLinkText
import io.github.droidkaigi.confsched2023.designsystem.preview.MultiLanguagePreviews
import io.github.droidkaigi.confsched2023.designsystem.preview.MultiThemePreviews
import io.github.droidkaigi.confsched2023.designsystem.theme.KaigiTheme
import io.github.droidkaigi.confsched2023.model.TimetableItem.Session
import io.github.droidkaigi.confsched2023.model.fake
import io.github.droidkaigi.confsched2023.model.nameAndFloor
import io.github.droidkaigi.confsched2023.sessions.SessionsStrings

@Composable
@@ -28,6 +32,7 @@ fun TimetableItemDetailSummaryCardRow(
content: String,
modifier: Modifier = Modifier,
leadingIconContentDescription: String? = null,
onContentClick: (() -> Unit)? = null,
) {
Row(
verticalAlignment = Alignment.CenterVertically,
@@ -46,7 +51,16 @@ fun TimetableItemDetailSummaryCardRow(
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
Spacer(modifier = Modifier.width(12.dp))
Text(text = content, style = MaterialTheme.typography.bodyMedium)
if (onContentClick == null) {
Text(text = content, style = MaterialTheme.typography.bodyMedium)
} else {
ClickableLinkText(
style = MaterialTheme.typography.bodyMedium,
content = content,
onLinkClick = { _ -> onContentClick() },
regex = ".*".toRegex(),
)
}
}
}

@@ -64,3 +78,18 @@ fun TimetableItemDetailSummaryCardRowPreview() {
}
}
}

@MultiThemePreviews
@Composable
fun TimetableItemDetailSummaryCardRowRoomPreview() {
KaigiTheme {
Surface {
TimetableItemDetailSummaryCardRow(
leadingIcon = Icons.Outlined.Schedule,
label = SessionsStrings.Place.asString(),
content = Session.fake().room.nameAndFloor,
onContentClick = {},
)
}
}
}
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@ internal fun TimetableItemDetail(
contentPadding: PaddingValues,
selectedLanguage: Lang?,
onLinkClick: (String) -> Unit,
onRoomClick: () -> Unit,
modifier: Modifier = Modifier,
) {
LazyColumn(
@@ -31,6 +32,7 @@ internal fun TimetableItemDetail(
TimetableItemDetailSummaryCard(
modifier = Modifier.padding(horizontal = 16.dp, vertical = 20.dp),
timetableItem = uiState.timetableItem,
onRoomClick = onRoomClick,
)
}