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

Extract the timetable item UI component as TimeTableItemCard and move it to the core:ui module #234

Merged
merged 16 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ class TimetableScreenRobot {
...
fun clickFirstSessionBookmark() {
composeTestRule
.onAllNodes(hasTestTag(TimetableListItemBookmarkIconTestTag))
.onAllNodes(hasTestTag(TimetableItemCardBookmarkIconTestTag))
.onFirst()
.performClick()
waitUntilIdle()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ import com.github.takahirom.roborazzi.RoborazziOptions
import com.github.takahirom.roborazzi.captureRoboImage
import io.github.droidkaigi.confsched.designsystem.theme.KaigiTheme
import io.github.droidkaigi.confsched.model.TimetableItem
import io.github.droidkaigi.confsched.sessions.TimetableListItemBookmarkIconTestTag
import io.github.droidkaigi.confsched.sessions.TimetableListItemTestTag
import io.github.droidkaigi.confsched.sessions.TimetableScreen
import io.github.droidkaigi.confsched.sessions.TimetableScreenTestTag
import io.github.droidkaigi.confsched.sessions.TimetableUiTypeChangeButtonTestTag
Expand All @@ -23,6 +21,8 @@ import io.github.droidkaigi.confsched.testing.DefaultScreenRobot
import io.github.droidkaigi.confsched.testing.DefaultTimetableServerRobot
import io.github.droidkaigi.confsched.testing.ScreenRobot
import io.github.droidkaigi.confsched.testing.TimetableServerRobot
import io.github.droidkaigi.confsched.ui.component.TimetableItemCardBookmarkIconTestTag
import io.github.droidkaigi.confsched.ui.component.TimetableItemCardTestTag
import io.github.droidkaigi.confsched.ui.compositionlocal.FakeClock
import io.github.droidkaigi.confsched.ui.compositionlocal.LocalClock
import javax.inject.Inject
Expand Down Expand Up @@ -51,15 +51,15 @@ class TimetableScreenRobot @Inject constructor(

fun clickFirstSession() {
composeTestRule
.onAllNodes(hasTestTag(TimetableListItemTestTag))
.onAllNodes(hasTestTag(TimetableItemCardTestTag))
.onFirst()
.performClick()
waitUntilIdle()
}

fun clickFirstSessionBookmark() {
composeTestRule
.onAllNodes(hasTestTag(TimetableListItemBookmarkIconTestTag))
.onAllNodes(hasTestTag(TimetableItemCardBookmarkIconTestTag))
.onFirst()
.performClick()
waitUntilIdle()
Expand Down Expand Up @@ -98,7 +98,7 @@ class TimetableScreenRobot @Inject constructor(

fun checkTimetableItemsDisplayed() {
composeTestRule
.onAllNodes(hasTestTag(TimetableListItemTestTag))
.onAllNodes(hasTestTag(TimetableItemCardTestTag))
.onFirst()
.assertIsDisplayed()
}
Expand Down
2 changes: 2 additions & 0 deletions core/ui/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ kotlin {
sourceSets {
commonMain {
dependencies {
implementation(projects.core.model)
implementation(projects.core.designsystem)
implementation(projects.core.data)
implementation(compose.materialIconsExtended)
implementation(libs.kermit)
api(projects.core.common)
api(libs.coil)
Expand Down
6 changes: 6 additions & 0 deletions core/ui/src/commonMain/composeResources/values-ja/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="bookmarked">ブックマーク済み</string>
<string name="not_bookmarked">ブックマークされていません</string>
<string name="image">画像</string>
</resources>
6 changes: 6 additions & 0 deletions core/ui/src/commonMain/composeResources/values/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="bookmarked">Bookmarked</string>
<string name="not_bookmarked">Not Bookmarked</string>
<string name="image">image</string>
</resources>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.github.droidkaigi.confsched.ui

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Circle
import androidx.compose.material.icons.filled.Square
import androidx.compose.material.icons.filled.Star
import androidx.compose.material.icons.filled.Thermostat
import androidx.compose.ui.graphics.vector.ImageVector
import io.github.droidkaigi.confsched.model.TimetableRoom

val TimetableRoom.icon: ImageVector
get() {
// TODO: Replace with the real icons. Probably need to embed them.
return when (name.enTitle) {
"Flamingo" -> Icons.Filled.Square
"Giraffe" -> Icons.Filled.Circle
"Hedgehog" -> Icons.Filled.Star
"Iguana" -> Icons.Filled.Thermostat
"Jellyfish" -> Icons.Filled.Star
else -> Icons.Filled.Star
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.github.droidkaigi.confsched.ui

import conference_app_2024.core.ui.generated.resources.Res

object UiRes {
val string = Res.string
val drawable = Res.drawable
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package io.github.droidkaigi.confsched.ui.component

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.outlined.FavoriteBorder
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
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.graphics.Color
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import conference_app_2024.core.ui.generated.resources.bookmarked
import conference_app_2024.core.ui.generated.resources.image
import conference_app_2024.core.ui.generated.resources.not_bookmarked
import io.github.droidkaigi.confsched.designsystem.theme.ProvideRoomTheme
import io.github.droidkaigi.confsched.model.TimetableItem
import io.github.droidkaigi.confsched.ui.UiRes
import io.github.droidkaigi.confsched.ui.rememberAsyncImagePainter
import org.jetbrains.compose.resources.stringResource

const val TimetableItemCardBookmarkIconTestTag = "TimetableListItemBookmarkIcon"
const val TimetableItemCardTestTag = "TimetableListItem"

@Composable
fun TimetableItemCard(
isBookmarked: Boolean,
timetableItem: TimetableItem,
tags: @Composable RowScope.() -> Unit,
onBookmarkClick: (TimetableItem, Boolean) -> Unit,
modifier: Modifier = Modifier,
onTimetableItemClick: (TimetableItem) -> Unit,
) {
ProvideRoomTheme(timetableItem.room.getThemeKey()) {
Column(
modifier = modifier
.border(
border = BorderStroke(width = 1.dp, color = MaterialTheme.colorScheme.outlineVariant),
shape = RoundedCornerShape(5.dp),
)
.padding(15.dp),
) {
Box {
Row(content = tags)
TextButton(
onClick = { onBookmarkClick(timetableItem, true) },
modifier = Modifier
.testTag(TimetableItemCardBookmarkIconTestTag)
.align(Alignment.TopEnd),
) {
if (isBookmarked) {
Icon(
Icons.Filled.Favorite,
contentDescription = stringResource(UiRes.string.bookmarked),
tint = Color.Green,
)
} else {
Icon(
Icons.Outlined.FavoriteBorder,
contentDescription = stringResource(UiRes.string.not_bookmarked),
tint = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
}
}

Text(
text = timetableItem.title.currentLangTitle,
fontSize = 24.sp,
modifier = Modifier
.testTag(TimetableItemCardTestTag)
.padding(bottom = 5.dp)
.clickable { onTimetableItemClick(timetableItem) },
)
timetableItem.speakers.forEach { speaker ->
Row {
// TODO: Fixed image loading again but its still slow. Maybe we need smaller images?
val painter = rememberAsyncImagePainter(speaker.iconUrl)
Image(
painter = painter,
modifier = Modifier
.width(32.dp)
.height(32.dp)
.clip(CircleShape),
contentDescription = stringResource(UiRes.string.image),
)
Text(
text = speaker.name,
fontSize = 24.sp,
color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier
.testTag(TimetableItemCardTestTag)
.padding(5.dp)
.align(Alignment.CenterVertically),
)
// TODO: Message goes here (missing from object we can access here?)
}
}
}
// TODO: There is no data for the warning string right now. (Should go here)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package io.github.droidkaigi.confsched.ui.component

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.unit.dp

@Composable
fun TimetableItemTag(
tagText: String,
tagColor: Color,
modifier: Modifier = Modifier,
icon: ImageVector? = null,
) {
Row(
modifier = modifier
.border(border = BorderStroke(width = 1.dp, color = tagColor))
.clip(RoundedCornerShape(15.dp))
.padding(5.dp),
) {
icon?.let { ico ->
Icon(ico, "", tint = tagColor)
}
Spacer(modifier = Modifier.padding(3.dp))
Text(
color = tagColor,
text = tagText,
modifier = Modifier.padding(end = 5.dp),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ import org.jetbrains.compose.resources.stringResource
import org.jetbrains.compose.ui.tooling.preview.Preview

const val timetableScreenRoute = "timetable"
const val TimetableListItemBookmarkIconTestTag = "TimetableListItemBookmarkIcon"
const val TimetableListItemTestTag = "TimetableListItem"
const val TimetableUiTypeChangeButtonTestTag = "TimetableUiTypeChangeButton"
fun NavGraphBuilder.nestedSessionScreens(
onTimetableItemClick: (TimetableItem) -> Unit,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import io.github.droidkaigi.confsched.designsystem.theme.KaigiTheme
import io.github.droidkaigi.confsched.designsystem.theme.LocalRoomTheme
import io.github.droidkaigi.confsched.model.TimetableItem
import io.github.droidkaigi.confsched.model.fake
import io.github.droidkaigi.confsched.sessions.section.TagView
import io.github.droidkaigi.confsched.ui.component.TimetableItemTag
import io.github.droidkaigi.confsched.ui.rememberAsyncImagePainter
import org.jetbrains.compose.ui.tooling.preview.Preview

Expand All @@ -41,13 +41,13 @@ fun TimetableItemDetailHeadline(
.fillMaxWidth(),
) {
Row {
TagView(
TimetableItemTag(
tagText = timetableItem.room.name.currentLangTitle,
tagColor = LocalRoomTheme.current.primaryColor,
)
timetableItem.language.labels.forEach { label ->
Spacer(modifier = Modifier.padding(4.dp))
TagView(
TimetableItemTag(
tagText = label,
tagColor = MaterialTheme.colorScheme.onSurfaceVariant,
)
Expand Down
Loading
Loading