Skip to content

Commit

Permalink
Merge pull request #755 from mangano-ito/748-timetabledetail-translat…
Browse files Browse the repository at this point in the history
…ion-button-more-visible

Introduce a language switcher to the timetable detail screen
  • Loading branch information
takahirom authored Aug 26, 2024
2 parents 649eadf + 2965993 commit df462b8
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,7 @@ private fun TimetableItemDetailScreen(
if (uiState is Loaded) {
ProvideRoomTheme(uiState.roomThemeKey) {
TimetableItemDetailTopAppBar(
isLangSelectable = uiState.isLangSelectable,
onNavigationIconClick = onNavigationIconClick,
onSelectedLanguage = onSelectedLanguage,
scrollBehavior = scrollBehavior,
)
}
Expand Down Expand Up @@ -229,6 +227,8 @@ private fun TimetableItemDetailScreen(
TimetableItemDetailHeadline(
currentLang = uiState.currentLang,
timetableItem = uiState.timetableItem,
isLangSelectable = uiState.isLangSelectable,
onLanguageSelect = onSelectedLanguage,
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,56 @@
package io.github.droidkaigi.confsched.sessions.component

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.selection.selectableGroup
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.VerticalDivider
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.CollectionInfo
import androidx.compose.ui.semantics.CollectionItemInfo
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.semantics.collectionInfo
import androidx.compose.ui.semantics.collectionItemInfo
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.role
import androidx.compose.ui.semantics.selected
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp
import conference_app_2024.feature.sessions.generated.resources.english
import conference_app_2024.feature.sessions.generated.resources.japanese
import conference_app_2024.feature.sessions.generated.resources.select_language
import io.github.droidkaigi.confsched.designsystem.theme.KaigiTheme
import io.github.droidkaigi.confsched.designsystem.theme.LocalRoomTheme
import io.github.droidkaigi.confsched.droidkaigiui.component.TimetableItemTag
import io.github.droidkaigi.confsched.droidkaigiui.rememberAsyncImagePainter
import io.github.droidkaigi.confsched.model.Lang
import io.github.droidkaigi.confsched.model.TimetableItem
import io.github.droidkaigi.confsched.model.fake
import io.github.droidkaigi.confsched.sessions.SessionsRes
import org.jetbrains.compose.resources.stringResource
import org.jetbrains.compose.ui.tooling.preview.Preview

const val TimetableItemDetailHeadlineTestTag = "TimetableItemDetailHeadlineTestTag"
Expand All @@ -37,17 +59,19 @@ const val TimetableItemDetailHeadlineTestTag = "TimetableItemDetailHeadlineTestT
fun TimetableItemDetailHeadline(
currentLang: Lang?,
timetableItem: TimetableItem,
isLangSelectable: Boolean,
onLanguageSelect: (Lang) -> Unit,
modifier: Modifier = Modifier,
) {
val currentLang = currentLang ?: Lang.ENGLISH
val currentLang = currentLang ?: timetableItem.language.toLang()
Column(
modifier = modifier
// FIXME: Implement and use a theme color instead of fixed colors like RoomColors.primary and RoomColors.primaryDim
.background(LocalRoomTheme.current.dimColor)
.padding(8.dp)
.padding(horizontal = 8.dp)
.fillMaxWidth(),
) {
Row {
Row(verticalAlignment = Alignment.CenterVertically) {
TimetableItemTag(
tagText = timetableItem.room.name.currentLangTitle,
tagColor = LocalRoomTheme.current.primaryColor,
Expand All @@ -59,6 +83,13 @@ fun TimetableItemDetailHeadline(
tagColor = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
Spacer(modifier = Modifier.weight(1f))
if (isLangSelectable) {
LanguageSwitcher(
currentLang = currentLang,
onLanguageSelect = onLanguageSelect,
)
}
}
Spacer(modifier = Modifier.height(16.dp))
Text(
Expand Down Expand Up @@ -98,6 +129,83 @@ fun TimetableItemDetailHeadline(
}
}

@Composable
private fun LanguageSwitcher(
currentLang: Lang,
onLanguageSelect: (Lang) -> Unit,
modifier: Modifier = Modifier,
) {
val normalizedCurrentLang = if (currentLang == Lang.MIXED) {
Lang.ENGLISH
} else {
currentLang
}
val availableLangs: Map<String, Lang> = mapOf(
stringResource(SessionsRes.string.japanese) to Lang.JAPANESE,
stringResource(SessionsRes.string.english) to Lang.ENGLISH,
)
val switcherContentDescription = stringResource(SessionsRes.string.select_language)
Row(
modifier = modifier
.selectableGroup()
.semantics {
contentDescription = switcherContentDescription
collectionInfo = CollectionInfo(
rowCount = availableLangs.size,
columnCount = 1,
)
},
verticalAlignment = Alignment.CenterVertically,
) {
val lastIndex = availableLangs.size - 1
availableLangs.entries.forEachIndexed { index, (label, lang) ->
val isSelected = normalizedCurrentLang == lang
TextButton(
onClick = { onLanguageSelect(lang) },
modifier = Modifier
.semantics {
role = Role.Tab
selected = isSelected
collectionItemInfo = CollectionItemInfo(
rowIndex = index,
rowSpan = 1,
columnIndex = 0,
columnSpan = 1,
)
},
contentPadding = PaddingValues(12.dp),
) {
val contentColor = if (isSelected) {
LocalRoomTheme.current.primaryColor
} else {
MaterialTheme.colorScheme.onSurfaceVariant
}
AnimatedVisibility(isSelected) {
Icon(
imageVector = Icons.Default.Check,
contentDescription = null,
modifier = Modifier
.padding(end = 4.dp)
.size(12.dp),
tint = contentColor,
)
}
Text(
text = label,
color = contentColor,
style = MaterialTheme.typography.labelMedium,
)
}
if (index < lastIndex) {
VerticalDivider(
modifier = Modifier.height(11.dp),
color = MaterialTheme.colorScheme.outlineVariant,
)
}
}
}
}

@Composable
@Preview
fun TimetableItemDetailHeadlinePreview() {
Expand All @@ -107,6 +215,8 @@ fun TimetableItemDetailHeadlinePreview() {
TimetableItemDetailHeadline(
timetableItem = TimetableItem.Session.fake(),
currentLang = Lang.JAPANESE,
isLangSelectable = true,
onLanguageSelect = {},
)
}
}
Expand All @@ -122,6 +232,8 @@ fun TimetableItemDetailHeadlineWithEnglishPreview() {
TimetableItemDetailHeadline(
timetableItem = TimetableItem.Session.fake(),
currentLang = Lang.ENGLISH,
isLangSelectable = true,
onLanguageSelect = {},
)
}
}
Expand All @@ -137,6 +249,8 @@ fun TimetableItemDetailHeadlineWithMixedPreview() {
TimetableItemDetailHeadline(
timetableItem = TimetableItem.Session.fake(),
currentLang = Lang.MIXED,
isLangSelectable = true,
onLanguageSelect = {},
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,39 +8,26 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBars
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
import androidx.compose.material.icons.outlined.GTranslate
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import conference_app_2024.feature.sessions.generated.resources.english
import conference_app_2024.feature.sessions.generated.resources.japanese
import io.github.droidkaigi.confsched.designsystem.theme.KaigiTheme
import io.github.droidkaigi.confsched.designsystem.theme.LocalRoomTheme
import io.github.droidkaigi.confsched.model.Lang
import io.github.droidkaigi.confsched.sessions.SessionsRes
import org.jetbrains.compose.resources.stringResource
import org.jetbrains.compose.ui.tooling.preview.Preview

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TimetableItemDetailTopAppBar(
isLangSelectable: Boolean,
onNavigationIconClick: () -> Unit,
onSelectedLanguage: (Lang) -> Unit,
scrollBehavior: TopAppBarScrollBehavior,
modifier: Modifier = Modifier,
) {
Expand Down Expand Up @@ -68,48 +55,6 @@ fun TimetableItemDetailTopAppBar(
)
}
},
actions = {
if (isLangSelectable) {
var expanded by remember { mutableStateOf(false) }

IconButton(onClick = { expanded = true }) {
Icon(
imageVector = Icons.Outlined.GTranslate,
contentDescription = "Select Language",
)
}

DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false },
) {
DropdownMenuItem(
text = {
Text(
text = stringResource(SessionsRes.string.japanese),
style = MaterialTheme.typography.bodySmall,
)
},
onClick = {
onSelectedLanguage(Lang.JAPANESE)
expanded = false
},
)
DropdownMenuItem(
text = {
Text(
text = stringResource(SessionsRes.string.english),
style = MaterialTheme.typography.bodySmall,
)
},
onClick = {
onSelectedLanguage(Lang.ENGLISH)
expanded = false
},
)
}
}
},
scrollBehavior = scrollBehavior,
)
}
Expand All @@ -122,9 +67,7 @@ fun TimetableItemDetailTopAppBarPreview() {
ProvideFakeRoomTheme {
Surface {
TimetableItemDetailTopAppBar(
isLangSelectable = true,
onNavigationIconClick = {},
onSelectedLanguage = {},
scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(),
)
}
Expand All @@ -140,9 +83,7 @@ fun TimetableItemDetailTopAppBarUnSelectablePreview() {
ProvideFakeRoomTheme {
Surface {
TimetableItemDetailTopAppBar(
isLangSelectable = false,
onNavigationIconClick = {},
onSelectedLanguage = {},
scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(),
)
}
Expand Down

0 comments on commit df462b8

Please sign in to comment.