Skip to content
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
1 change: 1 addition & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.texthip.thip.ui.common.alarmpage.component

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
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.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.texthip.thip.R
import com.texthip.thip.ui.common.buttons.OptionChipButton

@Composable
fun AlarmFilterRow(
selectedStates: BooleanArray,
onToggle: (Int) -> Unit
) {
Row(
horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
OptionChipButton(
text = stringResource(R.string.alarm_feed),
isFilled = true,
onClick = { onToggle(0) }
)
OptionChipButton(
text = stringResource(R.string.alarm_group),
isFilled = true,
onClick = { onToggle(1) }
)
Comment on lines +24 to +33

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

필터 상태가 UI에 반영되지 않는 문제가 있습니다.

selectedStates 매개변수를 받고 있지만 실제로는 사용하지 않고 있습니다. 모든 버튼이 항상 isFilled=true로 설정되어 있어 필터의 선택 상태가 시각적으로 표현되지 않습니다.

다음과 같이 수정하여 선택 상태를 반영하도록 해주세요:

        OptionChipButton(
            text = stringResource(R.string.alarm_feed),
-           isFilled = true,
+           isFilled = selectedStates[0],
            onClick = { onToggle(0) }
        )
        OptionChipButton(
            text = stringResource(R.string.alarm_group),
-           isFilled = true,
+           isFilled = selectedStates[1],
            onClick = { onToggle(1) }
        )
📝 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.

Suggested change
OptionChipButton(
text = stringResource(R.string.alarm_feed),
isFilled = true,
onClick = { onToggle(0) }
)
OptionChipButton(
text = stringResource(R.string.alarm_group),
isFilled = true,
onClick = { onToggle(1) }
)
OptionChipButton(
text = stringResource(R.string.alarm_feed),
isFilled = selectedStates[0],
onClick = { onToggle(0) }
)
OptionChipButton(
text = stringResource(R.string.alarm_group),
isFilled = selectedStates[1],
onClick = { onToggle(1) }
)
🤖 Prompt for AI Agents
In
app/src/main/java/com/texthip/thip/ui/common/alarmpage/component/AlarmFilterRow.kt
around lines 24 to 33, the OptionChipButton components always have isFilled set
to true, ignoring the selectedStates parameter, so the UI does not reflect the
filter selection state. Update the isFilled property of each OptionChipButton to
use the corresponding value from selectedStates to visually indicate whether
each filter is selected or not.

}
}

@Preview(showBackground = true)
@Composable
fun AlarmFilterRowPreview() {
var selectedStates by remember { mutableStateOf(booleanArrayOf(false, false)) }

AlarmFilterRow(
selectedStates = selectedStates,
onToggle = { idx ->
selectedStates = selectedStates.copyOf().also { it[idx] = !it[idx] }
}
)
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.texthip.thip.ui.common.alarmpage.mock

data class AlarmItem(
val id: Int,
val badgeText: String,
val title: String,
val message: String,
val timeAgo: String,
var isRead: Boolean
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package com.texthip.thip.ui.common.alarmpage.screen

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
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.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.texthip.thip.R
import com.texthip.thip.ui.common.alarmpage.component.AlarmFilterRow
import com.texthip.thip.ui.common.alarmpage.mock.AlarmItem
import com.texthip.thip.ui.common.cards.CardAlarm
import com.texthip.thip.ui.common.topappbar.DefaultTopAppBar
import com.texthip.thip.ui.theme.ThipTheme
import com.texthip.thip.ui.theme.ThipTheme.colors
import com.texthip.thip.ui.theme.ThipTheme.typography

@Composable
fun AlarmScreen(
alarmItems: List<AlarmItem>, onCardClick: (AlarmItem) -> Unit = {}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

사용되지 않는 매개변수 처리

onCardClick 매개변수가 제공되지만 실제로는 사용되지 않고 있습니다. 카드 클릭 시 내부 로직만 실행됩니다.

                            onClick = {
+                                onCardClick(alarm)
                                alarms = alarms.map {
                                    if (it.id == alarm.id) it.copy(isRead = true) else it
                                }
                            }

또는 이 매개변수가 필요하지 않다면 제거하는 것을 고려해보세요.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt
at line 37, the parameter onCardClick is declared but not used anywhere in the
function. Either remove the onCardClick parameter entirely if it is unnecessary,
or update the code to invoke onCardClick when a card is clicked to ensure the
parameter is utilized properly.

) {
var selectedStates by remember { mutableStateOf(booleanArrayOf(false, false)) }
var alarms by remember { mutableStateOf(alarmItems) }
Comment on lines +36 to +40

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

상태 관리 개선 필요

remember를 사용한 상태 관리는 화면 회전 등 설정 변경 시 상태가 초기화됩니다. 알림 읽음 상태를 보존하기 위해 rememberSaveable이나 ViewModel 사용을 고려해보세요.

-    var alarms by remember { mutableStateOf(alarmItems) }
+    var alarms by rememberSaveable { mutableStateOf(alarmItems) }

또는 ViewModel 패턴을 사용하여 상태를 관리하는 것이 더 나은 접근 방법입니다.

🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/ui/common/alarmpage/screen/AlarmScreen.kt
around lines 36 to 40, the current use of remember for state management causes
state loss on configuration changes like screen rotation. Replace remember with
rememberSaveable to preserve state across such changes, or refactor the state
management to use a ViewModel to hold and manage the alarm read states
persistently.


val filteredList = when {
selectedStates[0] && !selectedStates[1] -> alarms.filter { it.badgeText == stringResource(R.string.alarm_feed) }
!selectedStates[0] && selectedStates[1] -> alarms.filter { it.badgeText == stringResource(R.string.alarm_group) }
else -> alarms
}

Column(
Modifier
.fillMaxSize()
) {
DefaultTopAppBar(
title = stringResource(R.string.alarm_string),
onLeftClick = {},
)
Column(
Modifier
.fillMaxSize()
.padding(horizontal = 20.dp)
) {
Spacer(modifier = Modifier.height(20.dp))
AlarmFilterRow(
selectedStates = selectedStates, onToggle = { idx ->
selectedStates = selectedStates.copyOf().also { it[idx] = !it[idx] }
})
Spacer(modifier = Modifier.height(20.dp))

if (filteredList.isEmpty()) {

Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Icon(
painter = painterResource(R.drawable.ic_notification),
contentDescription = null,
tint = colors.Grey02,
)
Spacer(modifier = Modifier.height(12.dp))
Text(
text = stringResource(R.string.alarm_notification_comment),
style = typography.smalltitle_sb600_s16_h20,
color = colors.Grey01
)
}
} else {
LazyColumn(
verticalArrangement = Arrangement.spacedBy(20.dp),
contentPadding = PaddingValues(bottom = 20.dp),
modifier = Modifier.fillMaxSize()
) {
items(filteredList, key = { it.id }) { alarm ->
CardAlarm(
badgeText = alarm.badgeText,
title = alarm.title,
message = alarm.message,
timeAgo = alarm.timeAgo,
isRead = alarm.isRead,
onClick = {
alarms = alarms.map {
if (it.id == alarm.id) it.copy(isRead = true) else it
}
})
}
}
}
}
}
}


@Preview(showBackground = true)
@Composable
fun AlarmScreenPreview() {
ThipTheme {
AlarmScreen(
alarmItems = listOf(
AlarmItem(1, "피드", "내 글을 좋아합니다.", "user123님이 내 글에 좋아요를 눌렀어요.", "2", false),
AlarmItem(2, "모임", "같이 읽기를 시작했어요!", "모임방에서 20분 동안 같이 읽기가 시작되었어요!", "7", false),
AlarmItem(3, "피드", "내 글에 댓글이 달렸어요.", "user1: 진짜 공감합니다!", "2025.01.12", true),
AlarmItem(4, "모임", "투표가 시작되었어요!", "투표지를 먼저 열람합니다.", "17", false)
)
)
}
}

@Preview(showBackground = true)
@Composable
fun AlarmScreenEmptyPreview() {
ThipTheme {
AlarmScreen(
alarmItems = emptyList()
)
}
}
21 changes: 13 additions & 8 deletions app/src/main/java/com/texthip/thip/ui/common/cards/CardAlarm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import androidx.compose.foundation.layout.Column
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.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
Expand Down Expand Up @@ -42,8 +44,8 @@ fun CardAlarm(
message: String,
timeAgo: String,
isRead: Boolean = false,
containerColorUnread: Color = colors.DarkGrey, // 안읽음 상태의 배경색
containerColorRead: Color = colors.DarkGrey02, // 읽음 상태의 배경색
containerColorUnread: Color = colors.DarkGrey02, // 안읽음 상태의 배경색
containerColorRead: Color = colors.DarkGrey03, // 읽음 상태의 배경색
onClick: () -> Unit = {}
) {
Card(
Expand Down Expand Up @@ -86,19 +88,20 @@ fun CardAlarm(
)
}

Spacer(modifier = Modifier.width(12.dp))
Spacer(modifier = Modifier.width(8.dp))

// 내용 (제목, 빨간 점, 시간, 메시지)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

스크린샷에서 빨간점의 위치가 피그마랑 살짝 다른거같은데 .. 제 눈이 이상한걸수도 있고 .. ㅎ.ㅎ... 작아서 잘 모르겠긴 한데 .. 아무튼 그렇습니다 수정할 수 있으면 수정해주세욧

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

이전에 했던거라 생각 못했는데 확인하고 수정하겠습니다!

Column(
modifier = Modifier.weight(1f)
modifier = Modifier.weight(1f),
verticalArrangement = Arrangement.Center
) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = title,
style = typography.menu_sb600_s14_h24,
style = typography.view_m500_s14,
color = if (isRead) colors.Grey01 else colors.White,
modifier = Modifier.weight(1f),
maxLines = 1,
Expand All @@ -110,7 +113,6 @@ fun CardAlarm(
) {
// 안읽음 상태일 때만 빨간 점
if (!isRead) {
Spacer(modifier = Modifier.width(8.dp))
Box(
modifier = Modifier
.size(6.dp)
Expand All @@ -121,15 +123,18 @@ fun CardAlarm(

Text(
text = timeAgo + stringResource(R.string.time_ago),
style = typography.view_m500_s12_h20,
style = typography.timedate_r400_s11,
color = if (isRead) colors.Grey02 else colors.Grey01,
modifier = Modifier
.padding(top = 7.dp, end = 2.dp)
.offset(y = (-5).dp)
)
}
}
}
}

Spacer(modifier = Modifier.width(12.dp))
Spacer(modifier = Modifier.height(10.dp))

Text(
text = message,
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/java/com/texthip/thip/ui/theme/Color.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ val Grey02 = Color(0xFF888888)
val Grey03 = Color(0xFF525252)
val DarkGrey = Color(0xFF3D3D3D)
val DarkGrey50 = Color(0x803D3D3D)
val DarkGrey03 = Color(0xFF1D1D1D)
val DarkGrey02 = Color(0xFF282828)
val DarkGrey01 = Color(0x4B4B4B4B)
val Black = Color(0xFF121212)
Expand Down Expand Up @@ -71,6 +72,7 @@ data class ThipColors(
val DarkGrey: Color,
val darkGray01: Color,
val DarkGrey50: Color,
val DarkGrey03: Color,
val DarkGrey02: Color,
val Black: Color,
val Black50: Color,
Expand Down Expand Up @@ -106,6 +108,7 @@ val defaultThipColors = ThipColors(
DarkGrey = DarkGrey,
darkGray01 = DarkGrey01,
DarkGrey50 = DarkGrey50,
DarkGrey03 = DarkGrey03,
DarkGrey02 = DarkGrey02,
Black = Black,
Black50 = Black50,
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,12 @@
<string name="view_by_page">페이지별 보기</string>
<string name="view_by_all">총평 보기</string>

<!-- alarm -->
<string name="alarm_feed">피드</string>
<string name="alarm_group">모임</string>
<string name="alarm_string">알림</string>
<string name="alarm_notification_comment">새로운 알림이 없어요</string>

<!-- group makeroom -->
<string name="group_making_group">모임 만들기</string>
<string name="group_saved_book">저장한 책</string>
Expand Down