-
Notifications
You must be signed in to change notification settings - Fork 0
[feat/#14] Community UI #15
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
Conversation
WalkthroughThis PR implements the community UI feature for the app, introducing multiple Compose screens, navigation routes, reusable UI components, data models, and drawable resources. It also updates existing design system components and removes a placeholder file. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant MainTab
participant CommunityScreen
participant CommunityPostScreen
participant CommunityWritingScreen
User->>MainTab: Navigate to Community
MainTab->>CommunityScreen: Show main screen with tabs
CommunityScreen->>CommunityScreen: Render posts list
User->>CommunityScreen: Select tab
CommunityScreen->>CommunityScreen: Filter posts by tab
User->>CommunityScreen: Tap post card
CommunityScreen->>CommunityPostScreen: navigateToPost(postId)
CommunityPostScreen->>CommunityPostScreen: Load post detail
CommunityPostScreen->>CommunityPostScreen: Display comments & input
User->>CommunityPostScreen: Delete comment
CommunityPostScreen->>CommunityPostScreen: Show confirmation dialog
User->>CommunityPostScreen: Confirm deletion
CommunityPostScreen->>CommunityPostScreen: Remove comment
User->>CommunityScreen: Tap write button
CommunityScreen->>CommunityWritingScreen: navigateWriteCommunity()
CommunityWritingScreen->>CommunityWritingScreen: Show write form with board/title/content
User->>CommunityWritingScreen: Enter content & submit
CommunityWritingScreen->>CommunityWritingScreen: Validate isDone state
User->>CommunityWritingScreen: Confirm upload
CommunityWritingScreen->>CommunityScreen: navigateToCommunity() on success
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
🧹 Nitpick comments (9)
app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTopBar.kt (1)
43-44: Consider parameterizing content descriptions for better accessibility.The hardcoded generic content descriptions ("leftIcon", "rightIconFirst", "rightIconSecond") don't convey meaningful information to screen reader users. For a reusable component, content descriptions should ideally be passed as parameters so callers can provide context-appropriate descriptions like "Navigate back", "Search", or "Add new post".
Consider adding nullable content description parameters:
fun HsLinkTopBar( modifier: Modifier = Modifier, title: @Composable () -> Unit = {}, @DrawableRes rightIconFirst: Int? = null, @DrawableRes rightIconSecond: Int? = null, @DrawableRes leftIcon: Int? = null, onRightIconFirstClick: () -> Unit = {}, onRightIconSecondClick: () -> Unit = {}, - onLeftIconClick: () -> Unit = {} + onLeftIconClick: () -> Unit = {}, + leftIconContentDescription: String? = null, + rightIconFirstContentDescription: String? = null, + rightIconSecondContentDescription: String? = null ) {Then use them in the Icon composables:
leftIcon?.let { Icon( imageVector = ImageVector.vectorResource(id = it), - contentDescription = "leftIcon", + contentDescription = leftIconContentDescription, modifier = Modifier.noRippleClickable(onClick = onLeftIconClick) ) }Also applies to: 55-56, 63-64
app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommunityTabLayout.kt (1)
36-80: LGTM! Solid tab layout implementation.The
CommunityTabLayoutcomposable is well-implemented with proper theme integration, custom indicator, and appropriate color handling for selected/unselected states.Optional micro-optimization: Consider computing
tabs.indexOf(selectedTab)once to avoid the duplicate call on lines 49 and 56.fun CommunityTabLayout( selectedTab: CommunityTab, onTabSelected: (CommunityTab) -> Unit, modifier: Modifier = Modifier ) { val tabs = CommunityTab.entries + val selectedIndex = tabs.indexOf(selectedTab) HorizontalDivider( thickness = 1.dp, color = HsLinkTheme.colors.Grey100, ) TabRow( - selectedTabIndex = tabs.indexOf(selectedTab), + selectedTabIndex = selectedIndex, modifier = modifier.fillMaxWidth(), contentColor = HsLinkTheme.colors.SkyBlue500, containerColor = HsLinkTheme.colors.Common, divider = {}, indicator = { tabPositions -> TabRowDefaults.SecondaryIndicator( - modifier = Modifier.tabIndicatorOffset(tabPositions[tabs.indexOf(selectedTab)]), + modifier = Modifier.tabIndicatorOffset(tabPositions[selectedIndex]), color = HsLinkTheme.colors.SkyBlue500, height = 2.dp ) }Note: With only 4 tabs, the performance impact is negligible, so this is purely a nice-to-have improvement.
app/src/main/java/com/hsLink/hslink/presentation/community/component/post/PostHeader.kt (1)
33-37: Remove redundant string interpolation.The string interpolation
"$authorName"is unnecessary sinceauthorNameis already a String.Apply this diff:
Text( - text = "$authorName", + text = authorName, color = HsLinkTheme.colors.Grey700, style = HsLinkTheme.typography.caption_12Normal )app/src/main/java/com/hsLink/hslink/presentation/community/screen/main/CommunityScreen.kt (1)
45-50: Consider moving the data class to a dedicated data/model package.The
CommunityPostdata class is currently defined within the screen file. For better organization and reusability, consider moving it to a dedicated data or model package (e.g.,com.hsLink.hslink.data.modelorcom.hsLink.hslink.presentation.community.model).app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommentItem.kt (1)
68-76: Externalize the content description stringHard-coding
"댓글 삭제"prevents localization and reuse. Please load it from a string resource instead.Apply this diff within
CommentItem:-import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource @@ - contentDescription = "댓글 삭제", + contentDescription = stringResource(id = R.string.content_description_comment_delete),Add the corresponding
content_description_comment_deleteentry to yourstrings.xml.app/src/main/java/com/hsLink/hslink/presentation/community/component/write/CommunityWriteButton.kt (1)
63-67: Externalize the button labelHard-coding
"글작성 마치기"blocks localization and reuse. Load this copy fromstrings.xml.Apply this diff:
-import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource @@ - Text( - text = "글작성 마치기", + Text( + text = stringResource(id = R.string.community_write_button_label), color = HsLinkTheme.colors.Common, style = HsLinkTheme.typography.btm_L )Add the
community_write_button_labelentry tostrings.xml.app/src/main/java/com/hsLink/hslink/presentation/community/navigation/main/Communitynavigation.kt (1)
18-20: Consider consistent spacing for parameter declarations.Line 18 has spaces around the colon (
navigateUp : () -> Unit), while lines 19-20 don't follow the same pattern. For consistency, consider removing the spaces or applying them uniformly.- navigateUp : () -> Unit, - navigateToWriting : () -> Unit, + navigateUp: () -> Unit, + navigateToWriting: () -> Unit, navigateToPost: (String) -> Unit,app/src/main/java/com/hsLink/hslink/presentation/community/screen/post/CommunityPostScreen.kt (2)
64-91: Test data semantics: timeAgo field contains student year.Line 70 assigns
"21학번"(student year/grade) to thetimeAgofield, which semantically should represent elapsed time. While this is test data that will be replaced, consider using semantically appropriate values during development to avoid confusion.
192-193: TODOs flagged for backend integration.Three TODO comments mark pending backend integration:
- Line 192: Comment send logic
- Line 207: Post delete logic
- Line 224: Comment delete logic
These align with the PR description stating test artifacts will be removed during server integration.
Do you want me to open tracking issues for these backend integration tasks?
Also applies to: 207-207, 224-224
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (33)
.idea/caches/deviceStreaming.xml(2 hunks)app/src/main/java/com/hsLink/hslink/core/DummyComponent.kt(0 hunks)app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkDialog.kt(1 hunks)app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTextField.kt(1 hunks)app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTopBar.kt(4 hunks)app/src/main/java/com/hsLink/hslink/data/local/PostDetail.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/community/CommunityScreen.kt(0 hunks)app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommentItem.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommunityCardItem.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommunityTabLayout.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/community/component/post/CommentInput.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/community/component/post/EmptyComment.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/community/component/post/PostContent.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/community/component/post/PostHeader.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/community/component/write/BoardSelectionField.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/community/component/write/CommunityWriteButton.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/community/navigation/main/Communitynavigation.kt(2 hunks)app/src/main/java/com/hsLink/hslink/presentation/community/navigation/post/CommunityPostNavigation.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/community/navigation/write/CommunityWriteNavigation.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/community/screen/main/CommunityScreen.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/community/screen/post/CommunityPostScreen.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/community/screen/write/CommunityWritingScreen.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/main/MainNavHost.kt(2 hunks)app/src/main/java/com/hsLink/hslink/presentation/main/MainNavigator.kt(2 hunks)app/src/main/java/com/hsLink/hslink/presentation/main/MainTab.kt(1 hunks)app/src/main/res/drawable/ic_community_arrow_down.xml(1 hunks)app/src/main/res/drawable/ic_community_arrow_up.xml(1 hunks)app/src/main/res/drawable/ic_community_button.xml(1 hunks)app/src/main/res/drawable/ic_community_kebab.xml(1 hunks)app/src/main/res/drawable/ic_community_post.xml(1 hunks)app/src/main/res/drawable/ic_community_post_leftarrow.xml(1 hunks)app/src/main/res/drawable/ic_community_post_send.xml(1 hunks)app/src/main/res/drawable/ic_community_write_close.xml(1 hunks)
💤 Files with no reviewable changes (2)
- app/src/main/java/com/hsLink/hslink/core/DummyComponent.kt
- app/src/main/java/com/hsLink/hslink/presentation/community/CommunityScreen.kt
🧰 Additional context used
🧬 Code graph analysis (20)
app/src/main/java/com/hsLink/hslink/presentation/community/navigation/write/CommunityWriteNavigation.kt (3)
app/src/main/java/com/hsLink/hslink/presentation/main/MainNavigator.kt (1)
navigate(36-54)app/src/main/java/com/hsLink/hslink/presentation/community/screen/write/CommunityWritingScreen.kt (1)
CommunityWritingRoute(45-56)app/src/main/java/com/hsLink/hslink/presentation/community/navigation/Communitynavigation.kt (4)
communityNavGraph(16-22)navigateToCommunity(12-14)@Serializable(24-25)CommunityRoute(19-21)
app/src/main/java/com/hsLink/hslink/data/local/PostDetail.kt (1)
app/src/main/java/com/hsLink/hslink/presentation/home/component/HomePostContainer.kt (1)
id(39-43)
app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommunityCardItem.kt (2)
app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Theme.kt (1)
HsLinkTheme(37-57)app/src/main/java/com/hsLink/hslink/presentation/home/component/HomeCardItem.kt (5)
HomeCardItem(37-91)HomeCardItem(27-34)HsLinkTheme(26-35)Text(58-81)Column(54-90)
app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTopBar.kt (2)
app/src/main/java/com/hsLink/hslink/presentation/home/HomeScreen.kt (1)
HsLinkTopBar(57-74)app/src/main/java/com/hsLink/hslink/core/util/Modifier.kt (1)
noRippleClickable(9-19)
app/src/main/java/com/hsLink/hslink/presentation/community/navigation/post/CommunityPostNavigation.kt (2)
app/src/main/java/com/hsLink/hslink/presentation/community/screen/post/CommunityPostScreen.kt (1)
CommunityPostRoute(46-55)app/src/main/java/com/hsLink/hslink/presentation/community/navigation/Communitynavigation.kt (4)
communityNavGraph(16-22)navigateToCommunity(12-14)CommunityRoute(19-21)@Serializable(24-25)
app/src/main/java/com/hsLink/hslink/presentation/community/screen/main/CommunityScreen.kt (6)
app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Theme.kt (1)
HsLinkTheme(37-57)app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTopBar.kt (1)
HsLinkTopBar(22-68)app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommunityTabLayout.kt (1)
CommunityTabLayout(36-80)app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommunityCardItem.kt (1)
CommunityCardItem(38-87)app/src/main/java/com/hsLink/hslink/presentation/community/CommunityScreen.kt (2)
CommunityScreen(17-27)CommunityRoute(10-15)app/src/main/java/com/hsLink/hslink/presentation/community/navigation/Communitynavigation.kt (3)
@Serializable(24-25)communityNavGraph(16-22)CommunityRoute(19-21)
app/src/main/java/com/hsLink/hslink/presentation/community/screen/post/CommunityPostScreen.kt (8)
app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Theme.kt (1)
HsLinkTheme(37-57)app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTopBar.kt (1)
HsLinkTopBar(22-68)app/src/main/java/com/hsLink/hslink/presentation/community/component/post/PostHeader.kt (1)
PostHeader(15-52)app/src/main/java/com/hsLink/hslink/presentation/community/component/post/PostContent.kt (1)
PostContent(13-37)app/src/main/java/com/hsLink/hslink/presentation/community/component/post/EmptyComment.kt (1)
EmptyComment(15-38)app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommentItem.kt (1)
CommentItem(24-79)app/src/main/java/com/hsLink/hslink/presentation/community/component/post/CommentInput.kt (1)
CommentInput(23-79)app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkDialog.kt (1)
HsLinkDialog(22-95)
app/src/main/java/com/hsLink/hslink/presentation/community/component/write/CommunityWriteButton.kt (2)
app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Theme.kt (1)
HsLinkTheme(37-57)app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkSelectButton.kt (2)
HsLinkSelectButton(157-182)HsLinkSelectButton(38-94)
app/src/main/java/com/hsLink/hslink/presentation/community/component/write/BoardSelectionField.kt (2)
app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Theme.kt (1)
HsLinkTheme(37-57)app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTextField.kt (1)
HsLinkTextField(35-106)
app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommunityTabLayout.kt (1)
app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Theme.kt (1)
HsLinkTheme(37-57)
app/src/main/java/com/hsLink/hslink/presentation/main/MainNavigator.kt (1)
app/src/main/java/com/hsLink/hslink/presentation/community/navigation/Communitynavigation.kt (3)
navigateToCommunity(12-14)communityNavGraph(16-22)@Serializable(24-25)
app/src/main/java/com/hsLink/hslink/presentation/main/MainNavHost.kt (3)
app/src/main/java/com/hsLink/hslink/presentation/community/navigation/main/Communitynavigation.kt (1)
communityNavGraph(16-30)app/src/main/java/com/hsLink/hslink/presentation/community/navigation/write/CommunityWriteNavigation.kt (1)
communityWriteNavGraph(16-28)app/src/main/java/com/hsLink/hslink/presentation/community/navigation/post/CommunityPostNavigation.kt (1)
communityPostNavGraph(19-29)
app/src/main/java/com/hsLink/hslink/presentation/community/screen/write/CommunityWritingScreen.kt (6)
app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Theme.kt (1)
HsLinkTheme(37-57)app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTopBar.kt (1)
HsLinkTopBar(22-68)app/src/main/java/com/hsLink/hslink/presentation/community/component/write/BoardSelectionField.kt (1)
BoardSelectionField(42-105)app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTextField.kt (1)
HsLinkTextField(35-106)app/src/main/java/com/hsLink/hslink/presentation/community/component/write/CommunityWriteButton.kt (1)
CommunityWriteButton(36-70)app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkDialog.kt (1)
HsLinkDialog(22-95)
app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkDialog.kt (1)
app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Theme.kt (1)
HsLinkTheme(37-57)
app/src/main/java/com/hsLink/hslink/presentation/community/component/post/PostContent.kt (1)
app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Theme.kt (1)
HsLinkTheme(37-57)
app/src/main/java/com/hsLink/hslink/presentation/community/component/post/EmptyComment.kt (1)
app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Theme.kt (1)
HsLinkTheme(37-57)
app/src/main/java/com/hsLink/hslink/presentation/community/component/post/CommentInput.kt (1)
app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Theme.kt (1)
HsLinkTheme(37-57)
app/src/main/java/com/hsLink/hslink/presentation/community/component/post/PostHeader.kt (1)
app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Theme.kt (1)
HsLinkTheme(37-57)
app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommentItem.kt (1)
app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Theme.kt (1)
HsLinkTheme(37-57)
app/src/main/java/com/hsLink/hslink/presentation/community/navigation/main/Communitynavigation.kt (1)
app/src/main/java/com/hsLink/hslink/presentation/community/screen/main/CommunityScreen.kt (1)
CommunityRoute(66-80)
🔇 Additional comments (31)
.idea/caches/deviceStreaming.xml (1)
333-344: LGTM! Device configurations are well-formed and appropriate.Both new Samsung device entries (S23 and S25 Edge) are properly formatted, use correct API levels and screen dimensions, and integrate cleanly with existing configurations. The additions support the community UI feature across multiple device form factors and resolutions.
Minor note: IDE cache files like this can occasionally cause merge conflicts across the team. Consider whether
.idea/caches/should be in.gitignoreto avoid future drift, though if standardized device configs are needed for team alignment, committing them is acceptable.Also applies to: 836-847
app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTopBar.kt (1)
29-31: LGTM! Good API enhancement for flexibility.The new callback parameters make the top bar component more flexible and maintainable. The default empty lambdas ensure backward compatibility with existing callers.
app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommunityTabLayout.kt (2)
18-27: LGTM! Preview function is well-structured.The preview correctly demonstrates the component with appropriate theming and a selected tab state.
29-34: LGTM! Clean enum definition.The
CommunityTabenum clearly defines the four tab types with appropriate Korean titles.app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkDialog.kt (5)
1-20: LGTM! Clean imports and package structure.All imports are necessary and properly organized. The package structure follows Android design system conventions.
22-31: Well-structured function signature.The composable follows Compose API guidelines with clear parameter naming and proper modifier placement.
32-42: Clean dialog layout structure.The dialog implementation properly handles dismissal and uses consistent theme values for styling.
43-53: Proper text styling with good visual hierarchy.Title and message text components correctly apply theme values and establish clear visual hierarchy.
97-110: Excellent preview implementation.The preview is properly scoped as private, wrapped in the app's theme, and demonstrates the component with realistic content.
app/src/main/res/drawable/ic_community_write_close.xml (1)
1-9: LGTM! Well-formed vector drawable.The close icon resource is properly structured with appropriate dimensions and path data.
app/src/main/res/drawable/ic_community_arrow_down.xml (1)
1-9: LGTM! Well-formed vector drawable.The down arrow icon is properly structured.
app/src/main/res/drawable/ic_community_post_leftarrow.xml (1)
1-20: LGTM! Well-formed vector drawable.The left arrow icon uses proper stroke styling with rounded caps and joins.
app/src/main/res/drawable/ic_community_post_send.xml (1)
1-13: LGTM! Well-formed vector drawable.The send icon is properly structured with appropriate stroke styling.
app/src/main/res/drawable/ic_community_arrow_up.xml (1)
1-9: LGTM! Well-formed vector drawable.The up arrow icon is properly structured and consistent with the down arrow counterpart.
app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTextField.kt (1)
96-102: Good fix! Prevents invalid resource ID usage.The change properly guards the icon rendering to only occur when
leadingIconResis non-null, preventing potential crashes from attempting to load resource ID 0.app/src/main/java/com/hsLink/hslink/data/local/PostDetail.kt (1)
1-21: LGTM! Clean data models.The
PostDetailandCommentdata classes provide appropriate structure for representing post and comment data in the community feature.app/src/main/java/com/hsLink/hslink/presentation/community/component/post/CommentInput.kt (1)
23-79: LGTM! Comment input implementation looks good.The component properly handles placeholder display, input state, and conditional send button enabling. The UI structure and logic are sound.
app/src/main/java/com/hsLink/hslink/presentation/community/component/post/EmptyComment.kt (1)
15-38: LGTM!The empty state component is well-structured with appropriate padding and typography. The implementation is clean and follows the established theming patterns.
app/src/main/res/drawable/ic_community_post.xml (1)
1-20: LGTM!The vector drawable is properly structured with appropriate dimensions and styling for a post/edit icon.
app/src/main/java/com/hsLink/hslink/presentation/community/component/post/PostContent.kt (1)
13-37: LGTM!The post content component is well-structured with clear separation between title and content, using appropriate typography and spacing.
app/src/main/java/com/hsLink/hslink/presentation/community/screen/write/CommunityWritingScreen.kt (1)
58-254: LGTM!The writing screen implementation is well-structured with:
- Proper state management for form inputs and UI states
- Character limits enforced correctly for title (30) and content (500)
- Appropriate validation logic for enabling submission
- User-friendly confirmation dialogs for exit and upload actions
The form validation and user experience flow are solid.
app/src/main/java/com/hsLink/hslink/presentation/community/screen/main/CommunityScreen.kt (2)
94-120: Hardcoded test data noted.The hardcoded post data for each tab is appropriate for UI development and testing. As noted in the PR description, these test artifacts will be removed during server integration.
189-228: LGTM!The floating action button implementation is clean with proper styling, shadow, and click handling for navigating to the writing screen.
app/src/main/java/com/hsLink/hslink/presentation/community/component/write/BoardSelectionField.kt (2)
21-25: LGTM!The
BoardTypeenum is well-defined with clear display names for each board category.
42-105: LGTM!The board selection field implementation is well-designed:
- Uses an overlay Box to prevent text input while maintaining the text field appearance
- Properly toggles border color based on focus and expansion states
- Icon changes appropriately between arrow up/down based on expansion
- Dropdown menu is properly styled and functional
The approach of using an empty
onValueChangedlambda (line 56) is intentional and correct for making this a selection-only field.app/src/main/java/com/hsLink/hslink/presentation/main/MainTab.kt (1)
8-8: LGTM!The import path update correctly reflects the new community navigation package structure introduced in this PR.
app/src/main/java/com/hsLink/hslink/presentation/community/navigation/post/CommunityPostNavigation.kt (1)
1-32: LGTM! Clean navigation implementation.The navigation setup follows Compose type-safe navigation patterns correctly with proper parameter passing and route configuration.
app/src/main/java/com/hsLink/hslink/presentation/main/MainNavigator.kt (1)
56-70: LGTM! Navigation methods added correctly.The new community navigation methods follow the established delegation pattern and integrate cleanly with the existing navigation structure.
app/src/main/java/com/hsLink/hslink/presentation/main/MainNavHost.kt (1)
28-45: LGTM! Navigation graphs wired correctly.The expanded community navigation setup properly integrates the write and post flows with appropriate callbacks, maintaining consistency with the existing navigation architecture.
app/src/main/java/com/hsLink/hslink/presentation/community/screen/post/CommunityPostScreen.kt (2)
98-197: Well-structured screen implementation.The UI composition is clean and maintainable:
- Proper state management with appropriate hoisting
- Good use of LazyColumn for scrollable content with IME padding
- Conditional rendering for empty comments state
- Correct key usage in
items()for stable list rendering- Dialog state management properly coordinated with selected item tracking
28-32: The review comment is incorrect. The import paths are actually correct.The script output confirms that all five component files (CommentItem, CommentInput, EmptyComment, PostHeader, PostContent) declare their package as
com.hsLink.hslink.presentation.community.component—exactly matching the import statements in CommunityPostScreen.kt.The review comment's premise that these components are in subdirectories (
component/main/orcomponent/post/) is false. The imports will compile successfully as written, and implementing the suggested changes would break the code by pointing to non-existent packages.Likely an incorrect or invalid review comment.
| Row( | ||
| modifier = Modifier.fillMaxWidth(), | ||
| horizontalArrangement = Arrangement.Center | ||
| ) { | ||
| Box( | ||
| modifier = Modifier | ||
| .background( | ||
| color = HsLinkTheme.colors.Grey100, | ||
| shape = RoundedCornerShape(8.dp) | ||
| ) | ||
| .noRippleClickable(onClick = onDismiss) | ||
| .padding(vertical = 12.dp, horizontal = 40.dp) | ||
| ) { | ||
| Text( | ||
| text = dismissText, | ||
| color = HsLinkTheme.colors.Grey500, | ||
| style = HsLinkTheme.typography.btm_M, | ||
| ) | ||
| } | ||
|
|
||
| Spacer(modifier = Modifier.width(8.dp)) | ||
|
|
||
| Box( | ||
| modifier = Modifier | ||
| .background( | ||
| color = HsLinkTheme.colors.DeepBlue500, | ||
| shape = RoundedCornerShape(8.dp) | ||
| ) | ||
| .noRippleClickable(onClick = onConfirm) | ||
| .padding(vertical = 12.dp, horizontal = 40.dp) | ||
| ) { | ||
| Text( | ||
| text = confirmText, | ||
| color = HsLinkTheme.colors.Common, | ||
| style = HsLinkTheme.typography.btm_M, | ||
| ) | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
🧩 Analysis chain
Verify touch target sizes meet accessibility guidelines.
The action buttons use 12.dp vertical padding. Depending on the btm_M typography's line height, the total touch target might fall short of the recommended 48dp minimum for accessibility.
Additionally, consider adding semantic properties to improve accessibility support, such as content descriptions or button roles.
Run the following script to check the btm_M typography definition and verify the touch target will be sufficient:
Alternatively, consider using Material3 Button or TextButton components, which provide built-in accessibility features and proper touch target sizing.
🏁 Script executed:
#!/bin/bash
# Find the btm_M typography definition to verify line height and size
ast-grep --pattern 'btm_M = TextStyle($$$)'Length of output: 0
🏁 Script executed:
#!/bin/bash
# Search for btm_M definition in the codebase
rg -n 'btm_M' --type=kt -C3Length of output: 26
🏁 Script executed:
#!/bin/bash
# Search for Typography or TextStyle definitions
rg -n 'object.*[Tt]ypography|val.*[Tt]ypography' --type=kt -A5 | head -50Length of output: 26
🏁 Script executed:
#!/bin/bash
# Find HsLinkTheme definition to understand the design system
fd -e 'kt' -x rg -l 'HsLinkTheme' | head -10Length of output: 925
🏁 Script executed:
#!/bin/bash
# Search for btm_M definition without file type restriction
rg -n 'btm_M' app/src/main/java/com/hsLink/hslink/core/designsystem/ -C3Length of output: 3809
🏁 Script executed:
#!/bin/bash
# Find theme or typography related files in designsystem
fd 'theme|typography|style' app/src/main/java/com/hsLink/hslink/core/designsystem/ -type fLength of output: 170
🏁 Script executed:
#!/bin/bash
# Search for HsLinkTheme definition
rg -n 'object HsLinkTheme|class HsLinkTheme' app/src/main/java/com/hsLink/hslink/core/designsystem/ -C5Length of output: 1108
🏁 Script executed:
#!/bin/bash
# Get complete btm_M definition from Type.kt
rg -n 'btm_M = TextStyle' app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Type.kt -A6Length of output: 229
Action buttons fall short of accessibility touch target minimum.
The button height is approximately 46.dp (22.sp lineHeight from btm_M + 24.dp vertical padding), which is 2.dp below the recommended 48.dp minimum touch target size per Material Design accessibility guidelines.
Consider either increasing vertical padding to 13.dp (making total height ~48.dp) or switching to Material3 Button or TextButton components, which provide built-in accessibility features and proper touch target sizing.
🤖 Prompt for AI Agents
In
app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkDialog.kt
around lines 55-92 the custom action button boxes produce an approximate 46.dp
height which is below the 48.dp accessibility touch target; either increase the
vertical padding to 13.dp for both action boxes (so total height ≈48.dp) or
replace the Box+Text combos with Material3 Button/TextButton components (or
apply Modifier.minimumInteractiveComponentSize(48.dp)) to ensure the touch
target meets 48.dp while preserving current colors, shapes and typography.
| @@ -0,0 +1,87 @@ | |||
| package com.hsLink.hslink.presentation.home.component | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Package declaration doesn't match file location.
The package is declared as com.hsLink.hslink.presentation.home.component, but the file is located in presentation/community/component/main/. This mismatch will cause compilation errors or incorrect imports.
Apply this diff to fix the package declaration:
-package com.hsLink.hslink.presentation.home.component
+package com.hsLink.hslink.presentation.community.component.main📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| package com.hsLink.hslink.presentation.home.component | |
| package com.hsLink.hslink.presentation.community.component.main |
🤖 Prompt for AI Agents
In
app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommunityCardItem.kt
around line 1, the package declaration is incorrect (currently
com.hsLink.hslink.presentation.home.component) and must match the file path;
change it to com.hsLink.hslink.presentation.community.component.main so the
package mirrors the directory structure and resolves compilation/import errors.
| @Composable | ||
| fun CommunityCardItem( | ||
| userName: String, | ||
| userMajor: String, | ||
| userInfo: String, | ||
| onClick: () -> Unit, | ||
| modifier: Modifier = Modifier, | ||
| ) { | ||
| Row( | ||
| modifier = modifier | ||
| .fillMaxWidth() | ||
| .border( | ||
| width = 1.dp, | ||
| color = HsLinkTheme.colors.Grey100, | ||
| shape = RoundedCornerShape(8.dp) | ||
| ) | ||
| .noRippleClickable(onClick = onClick) | ||
| .padding(16.dp), | ||
| verticalAlignment = Alignment.CenterVertically, | ||
| ) { | ||
| Column( | ||
| modifier = Modifier.weight(1f), | ||
| verticalArrangement = Arrangement.spacedBy(4.dp) | ||
| ) { | ||
| Text( | ||
| text = userName, | ||
| color = HsLinkTheme.colors.Grey700, | ||
| style = HsLinkTheme.typography.title_16Strong, | ||
| maxLines = 1, | ||
| overflow = TextOverflow.Ellipsis | ||
| ) | ||
|
|
||
| Text( | ||
| text = userMajor, | ||
| color = HsLinkTheme.colors.Grey700, | ||
| style = HsLinkTheme.typography.body_14Normal, | ||
| maxLines = 1, | ||
| overflow = TextOverflow.Ellipsis | ||
| ) | ||
|
|
||
| Text( | ||
| text = userInfo, | ||
| color = HsLinkTheme.colors.Grey400, | ||
| style = HsLinkTheme.typography.caption_12Normal, | ||
| maxLines = 1, | ||
| overflow = TextOverflow.Ellipsis | ||
| ) | ||
| } | ||
| } | ||
| } No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Significant code duplication with HomeCardItem.
This component shares nearly identical structure and styling with HomeCardItem (found in presentation/home/component/HomeCardItem.kt). The only differences are the onClick handler and the trailing icon. Consider extracting a shared base component to reduce duplication and improve maintainability.
Additionally, HomeCardItem displays an arrow icon to visually indicate it's interactive, while CommunityCardItem is clickable but lacks any visual affordance. For UX consistency, consider adding a visual indicator (icon or similar) to signal the clickable nature of this card.
Possible refactoring approach:
Create a shared internal composable that both components can use:
@Composable
private fun BaseCardItem(
userName: String,
userMajor: String,
userInfo: String,
modifier: Modifier = Modifier,
trailingContent: @Composable (() -> Unit)? = null,
onClick: (() -> Unit)? = null,
) {
Row(
modifier = modifier
.fillMaxWidth()
.border(
width = 1.dp,
color = HsLinkTheme.colors.Grey100,
shape = RoundedCornerShape(8.dp)
)
.then(if (onClick != null) Modifier.noRippleClickable(onClick = onClick) else Modifier)
.padding(16.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Column(
modifier = Modifier.weight(1f),
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
Text(
text = userName,
color = HsLinkTheme.colors.Grey700,
style = HsLinkTheme.typography.title_16Strong,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Text(
text = userMajor,
color = HsLinkTheme.colors.Grey700,
style = HsLinkTheme.typography.body_14Normal,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Text(
text = userInfo,
color = HsLinkTheme.colors.Grey400,
style = HsLinkTheme.typography.caption_12Normal,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
trailingContent?.let {
Spacer(modifier = Modifier.weight(1f))
it()
}
}
}Then simplify both components to use this base.
🤖 Prompt for AI Agents
In
app/src/main/java/com/hsLink/hslink/presentation/community/component/main/CommunityCardItem.kt
around lines 38-87, this composable duplicates most of HomeCardItem and lacks a
visual affordance for clickability; extract a shared internal BaseCardItem that
contains the Row/Column/Text layout and accepts optional onClick and
trailingContent parameters, then refactor CommunityCardItem (and HomeCardItem)
to call BaseCardItem passing their onClick and appropriate trailingContent
(e.g., the arrow icon) to remove duplication and restore consistent clickable
affordance.
| @@ -0,0 +1,91 @@ | |||
| package com.hsLink.hslink.presentation.community.component | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix package declaration mismatch.
The package declaration does not match the file path. The file is located in .../component/post/ but the package is declared as .../component. This will cause compilation errors.
Apply this diff:
-package com.hsLink.hslink.presentation.community.component
+package com.hsLink.hslink.presentation.community.component.post📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| package com.hsLink.hslink.presentation.community.component | |
| package com.hsLink.hslink.presentation.community.component.post |
🤖 Prompt for AI Agents
In
app/src/main/java/com/hsLink/hslink/presentation/community/component/post/CommentInput.kt
around line 1, the package declaration currently states
com.hsLink.hslink.presentation.community.component but the file resides in the
component/post directory; update the package declaration to
com.hsLink.hslink.presentation.community.component.post so the package matches
the file path and resolves the compilation error.
| modifier = modifier | ||
| .fillMaxWidth() | ||
| .background(backColor, shape = RoundedCornerShape(8.dp)) | ||
| .noRippleClickable(onClick = onClick) | ||
| .padding(vertical = 12.dp), | ||
| horizontalArrangement = Arrangement.Center, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Block clicks until writing is complete
noRippleClickable stays enabled even when isDone is false, so the finish action is still fireable while the UI looks disabled. Guard the click with enabled = isDone (or equivalent) so unfinished drafts cannot be submitted.
Apply this diff:
modifier = modifier
.fillMaxWidth()
.background(backColor, shape = RoundedCornerShape(8.dp))
- .noRippleClickable(onClick = onClick)
+ .noRippleClickable(
+ onClick = onClick,
+ enabled = isDone
+ )
.padding(vertical = 12.dp),Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In
app/src/main/java/com/hsLink/hslink/presentation/community/component/write/CommunityWriteButton.kt
around lines 47 to 52, the noRippleClickable handler is active even when isDone
is false so the finish action can be triggered while the UI appears disabled;
update the click guard so the clickable is disabled when isDone is false — e.g.,
pass enabled = isDone into the clickable/noRippleClickable call or wrap the
onClick with an if (isDone) check so clicks are ignored until isDone is true,
ensuring the visual disabled state matches actual behavior.
| import com.hsLink.hslink.core.util.noRippleClickable | ||
| import com.hsLink.hslink.presentation.community.component.CommunityTab | ||
| import com.hsLink.hslink.presentation.community.component.CommunityTabLayout | ||
| import com.hsLink.hslink.presentation.home.component.CommunityCardItem |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify the import path for CommunityCardItem.
The import references com.hsLink.hslink.presentation.home.component.CommunityCardItem, but given this is community UI functionality, the component might be better located in the community package structure.
Run this script to check where CommunityCardItem is defined and used:
🏁 Script executed:
#!/bin/bash
# Find CommunityCardItem definition and usages
echo "=== CommunityCardItem definition ==="
ast-grep --pattern $'@Composable
fun CommunityCardItem($$$) {
$$$
}'
echo -e "\n=== CommunityCardItem import statements ==="
rg -n "import.*CommunityCardItem"Length of output: 6617
Fix incorrect import path for CommunityCardItem.
The import com.hsLink.hslink.presentation.home.component.CommunityCardItem is incorrect. The component is defined in com.hsLink.hslink.presentation.community.component.main.CommunityCardItem (line 39 of CommunityCardItem.kt). Update the import to reference the correct package path.
🤖 Prompt for AI Agents
In
app/src/main/java/com/hsLink/hslink/presentation/community/screen/main/CommunityScreen.kt
around line 43, the import path for CommunityCardItem is incorrect; replace the
current import com.hsLink.hslink.presentation.home.component.CommunityCardItem
with the correct package
com.hsLink.hslink.presentation.community.component.main.CommunityCardItem so the
file references the component where it is actually defined.
ISSUE
❗ WORK DESCRIPTIONAdd commentMore actions
📸 SCREENSHOT
-.Clipchamp.4.mp4
📢 TO REVIEWERS
Summary by CodeRabbit
Release Notes
New Features
Bug Fixes
Chores