Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
633557a
[refactor]: LogotopAppbar 우측 아이콘 수정 (#102)
rbqks529 Aug 19, 2025
8e5cee4
[refactor]: 책 자세히보기 화면 우측 버튼 삭제 및 gradient 수정 (#102)
rbqks529 Aug 19, 2025
a0bb368
[refactor]: 책 자세히보기 화면에서 피드 작성 화면으로 네비게이션 (#102)
rbqks529 Aug 19, 2025
ce25137
[refactor]: 모임 생성 화면 장르 왼쪽 정렬 및 다중 선택 가능하게 수정 (#102)
rbqks529 Aug 19, 2025
616608a
[refactor]: 모임 생성 화면 비율 수정 및 내일부터 선택 가능하게 수정 (#102)
rbqks529 Aug 19, 2025
ba47bd9
[refactor]: 피드 작성 후 새로 고침 및 피드 상단 알림페이지 네비게이션 구현 (#102)
rbqks529 Aug 19, 2025
ef4b7e9
[refactor]: 피드 자세히보기 화면 네비게이션 추가 (#102)
rbqks529 Aug 19, 2025
98c5953
[refactor]: 상당 토스트 메세지 애니메이션 및 시간 통일 (#102)
rbqks529 Aug 19, 2025
a7e7dd6
[refactor]: 바텀 시트 키보드 패딩 추가 (#102)
rbqks529 Aug 19, 2025
ff4da7d
[refactor]: 책 검색 패딩 수정 (#102)
rbqks529 Aug 19, 2025
67d7cdc
[refactor]: 모집중인 모임방 화면 내부 정렬 수정 (#102)
rbqks529 Aug 19, 2025
60ecacb
[refactor]: 모집중인 모임방 dto 수정 (#102)
rbqks529 Aug 19, 2025
20222ef
[refactor]: 모집중인 화면 비율 수정 (#102)
rbqks529 Aug 19, 2025
b000d81
[refactor]: 비밀번호 입력 화면 커서 로직 수정 (#102)
rbqks529 Aug 19, 2025
619cae4
[refactor]: 피드 책 영역 부분 "저"가 항상 보이게 수정 (#102)
rbqks529 Aug 19, 2025
80711ea
[refactor]: 네비게이션 시 상태 초기화 (#102)
rbqks529 Aug 19, 2025
c82b822
[refactor]: 피드 화면 변경시 indicator 추가 (#102)
rbqks529 Aug 19, 2025
ca77fa2
develop branch 최신화
rbqks529 Aug 19, 2025
db817d8
Merge branch 'develop' into refactor/#102_QA
Nico1eKim Aug 20, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ data class RoomRecruitingResponse(
@Serializable
data class RecommendRoomResponse(
@SerialName("roomId") val roomId: Int,
@SerialName("roomImageUrl") val roomImageUrl: String?,
@SerialName("bookImageUrl") val bookImageUrl: String?,
@SerialName("roomName") val roomName: String,
@SerialName("memberCount") val memberCount: Int,
@SerialName("recruitCount") val recruitCount: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import com.texthip.thip.ui.theme.ThipTheme
import com.texthip.thip.ui.theme.ThipTheme.colors
import com.texthip.thip.utils.rooms.advancedImePadding
import kotlinx.coroutines.launch

private const val BOTTOM_SHEET_HIDDEN_OFFSET = 300f
Expand Down Expand Up @@ -93,6 +94,7 @@ fun CustomBottomSheet(
modifier = Modifier
.fillMaxWidth()
.offset(y = (offsetY + animatableOffset.value).dp)
.advancedImePadding()
.background(
color = colors.DarkGrey,
shape = RoundedCornerShape(topEnd = 12.dp, topStart = 12.dp)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
Expand Down Expand Up @@ -51,16 +52,25 @@ fun ActionBookButton(
maxLines = 1
)

// 저자명과 "저"를 분리
Text(
text = bookAuthor + stringResource(R.string.author),
text = bookAuthor,
style = typography.info_r400_s12_h24,
color = colors.Grey,
modifier = Modifier.width(100.dp),
modifier = Modifier
.widthIn(max = 80.dp)
.padding(start = 8.dp),
textAlign = TextAlign.Right,
overflow = TextOverflow.Ellipsis,
maxLines = 1
)

Text(
text = stringResource(R.string.author),
style = typography.info_r400_s12_h24,
color = colors.Grey,
)
Comment on lines +55 to +72
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

저자명과 ‘저’를 분리한 건 👍. 다음 두 가지를 개선해 주세요 (현지화/접근성 친화).

  • RTL 안전 정렬: TextAlign.Right 대신 TextAlign.End를 사용해 레이아웃 방향을 따른 정렬을 권장합니다.
  • 공백/따옴표를 문자열 리소스에 넣지 않기: 문자열에 선행 공백이나 따옴표를 포함시키면 현지화, 접근성, 줄바꿈 제어가 어려워집니다. UI에서 padding(start = …)로 간격을 주는 방식으로 정리하는 것을 권장합니다.

아래 diff는 컴포넌트 내에서 가능한 최소 변경입니다(문자열 리소스의 선행 공백 제거가 전제되면 시각적 일관성이 좋아집니다).

-                textAlign = TextAlign.Right,
+                textAlign = TextAlign.End,
                 overflow = TextOverflow.Ellipsis,
                 maxLines = 1
             )
 
-            Text(
+            Text(
                 text = stringResource(R.string.author),
                 style = typography.info_r400_s12_h24,
-                color = colors.Grey,
+                color = colors.Grey,
+                modifier = Modifier.padding(start = 4.dp),
             )

추가로, widthIn(max = 80.dp)는 폰트 스케일이 큰 환경에서 너무 촘촘할 수 있습니다. 필요시 96dp 정도로 여유를 주거나, 상황에 따라 조건부로 완화하는 것도 고려해 볼 수 있습니다.

문자열 리소스에 선행 공백이나 따옴표가 포함되어 있는지 확인해 주세요. 포함되어 있다면 제거하는 것을 권장합니다.


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "author 문자열 리소스 내용 확인"
fd strings.xml | xargs -I{} rg -n '<string name="author">.*</string>' {}

Length of output: 192


RTL 정렬 및 문자열 리소스 정리 필수 반영

  • ActionBookButton.kt (55–72줄)
    TextAlign.RightTextAlign.End (RTL 안전 정렬)
    • 두 번째 TextModifier.padding(start = 4.dp) 추가 (문자열 리소스에 공백 제거)
    • (선택) 첫 번째 TextwidthIn(max = 80.dp)96.dp로 여유 부여 고려
  • strings.xml
    <string name="author">" 저"</string><string name="author">저</string>
--- a/app/src/main/java/com/texthip/thip/ui/common/buttons/ActionBookButton.kt
@@ -55,8 +55,9 @@
             Text(
                 text = bookAuthor,
                 style = typography.info_r400_s12_h24,
                 color = colors.Grey,
                 modifier = Modifier
                     .widthIn(max = 80.dp)
                     .padding(start = 8.dp),
-                textAlign = TextAlign.Right,
+                textAlign = TextAlign.End,
                 overflow = TextOverflow.Ellipsis,
                 maxLines = 1
             )
@@ -64,6 +65,7 @@
             Text(
                 text = stringResource(R.string.author),
                 style = typography.info_r400_s12_h24,
                 color = colors.Grey,
+                modifier = Modifier.padding(start = 4.dp),
             )
--- a/app/src/main/res/values/strings.xml
@@ -27,7 +27,7 @@
     <!-- 저자 표시 -->
-    <string name="author">" 저"</string>
+    <string name="author">저</string>
🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/ui/common/buttons/ActionBookButton.kt
around lines 55 to 72, replace TextAlign.Right with TextAlign.End for RTL-safe
alignment, add Modifier.padding(start = 4.dp) to the second Text (the author
label) to restore spacing removed from the string resource, and optionally
increase the first Text's widthIn(max = 80.dp) to widthIn(max = 96.dp) if extra
space is desired; also update strings.xml to change <string name="author">"
저"</string> to <string name="author">저</string> (remove quotes and leading
space).


Icon(
painter = painterResource(R.drawable.ic_chevron),
contentDescription = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ fun GenreChipRow(
modifier: Modifier = Modifier.width(4.dp),
genres: List<String>,
selectedIndex: Int,
onSelect: (Int) -> Unit
onSelect: (Int) -> Unit,
horizontalArrangement: Arrangement.Horizontal = Arrangement.Center
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Center
horizontalArrangement = horizontalArrangement
) {
genres.forEachIndexed { idx, genre ->
OptionChipButton(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ import com.texthip.thip.ui.theme.ThipTheme
fun SubGenreChipGrid(
subGenres: List<String>,
selectedGenres: List<String>,
onGenreToggle: (String) -> Unit
onGenreToggle: (String) -> Unit,
horizontalAlignment: Alignment.Horizontal = Alignment.CenterHorizontally
) {
FlowRow(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterHorizontally),
horizontalArrangement = Arrangement.spacedBy(8.dp, horizontalAlignment),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
subGenres.forEach { genre ->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.texthip.thip.ui.common.forms

import android.view.KeyEvent
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
Expand All @@ -12,16 +11,16 @@ import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.input.key.KeyEventType
import androidx.compose.ui.input.key.onKeyEvent
import androidx.compose.ui.input.key.type
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
Expand All @@ -39,6 +38,15 @@ fun SingleDigitBox(
containerColor: Color = colors.darkGray01,
borderColor: Color = Color.Transparent
) {
// TextFieldValue로 커서 위치 제어
val textFieldValue = remember(value) {
val displayText = value.ifEmpty { "\u200B" } // Zero Width Space
TextFieldValue(
text = displayText,
selection = TextRange(displayText.length) // 커서를 맨 끝에 위치
)
}

val myStyle = typography.smalltitle_sb600_s18_h24.copy(
lineHeight = 20.sp,
textAlign = TextAlign.Center,
Expand All @@ -53,37 +61,32 @@ fun SingleDigitBox(
contentAlignment = Alignment.Center
) {
BasicTextField(
value = value,
onValueChange = { input ->
val filtered = input.filter { it.isDigit() }.take(1)
value = textFieldValue,
onValueChange = { newValue ->
val cleaned = newValue.text.replace("\u200B", "")
Comment on lines 63 to +66
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

포커스 이동이 동작하지 않음/크래시 가능성: FocusRequester가 BasicTextField에 연결되지 않았습니다

현재 FocusRequester는 호출 측에서 SingleDigitBox의 modifier에 붙고, 내부에서는 그 modifier를 Box에만 적용합니다. Box는 포커스 타겟이 아니므로 requestFocus() 시 IllegalStateException이 발생하거나 포커스가 무시될 수 있습니다. BasicTextField에 modifier를 전달해 FocusRequester가 실제 포커스 타겟에 연결되도록 해야 합니다.

다음 최소 수정으로 해결 가능합니다(공개 API 변경 없음):

         BasicTextField(
+            modifier = modifier,
             value = textFieldValue,
             onValueChange = { newValue ->
📝 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
BasicTextField(
value = value,
onValueChange = { input ->
val filtered = input.filter { it.isDigit() }.take(1)
value = textFieldValue,
onValueChange = { newValue ->
val cleaned = newValue.text.replace("\u200B", "")
BasicTextField(
modifier = modifier,
value = textFieldValue,
onValueChange = { newValue ->
val cleaned = newValue.text.replace("\u200B", "")

val filtered = cleaned.filter { it.isDigit() }.take(1)

// 백스페이스 감지: Zero Width Space가 지워졌을 때
if (newValue.text.isEmpty() && value.isEmpty()) {
onBackspace?.invoke()
return@BasicTextField
}

onValueChange(filtered)
},
textStyle = myStyle,
textStyle = myStyle.copy(
color = if (value.isEmpty()) Color.Transparent else colors.White
),
singleLine = true,
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.NumberPassword),
modifier = modifier
.background(containerColor, RoundedCornerShape(12.dp))
.border(1.dp, borderColor, RoundedCornerShape(12.dp))
.onKeyEvent { keyEvent ->
if (keyEvent.nativeKeyEvent.keyCode == KeyEvent.KEYCODE_DEL &&
keyEvent.type == KeyEventType.KeyDown
) {
if (value.isEmpty()) {
onBackspace?.invoke()
true
} else {
false
}
} else {
false
}
},
cursorBrush = SolidColor(colors.NeonGreen),
decorationBox = { innerTextField ->
Box(
Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) { innerTextField() }
) {
innerTextField()
}
}
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.texthip.thip.ui.common.topappbar

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
Expand All @@ -9,6 +10,11 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
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.graphics.Brush
Expand All @@ -20,14 +26,39 @@ import androidx.compose.ui.unit.dp
import com.texthip.thip.R
import com.texthip.thip.ui.common.view.CountingBar
import com.texthip.thip.ui.theme.ThipTheme.colors
import kotlinx.coroutines.delay

@Composable
fun GradationTopAppBar(
isImageVisible: Boolean = false,
count: Int = 0,
autoHideCount: Boolean? = null,
countDisplayDurationMs: Long = 5000L,
onLeftClick: () -> Unit,
onRightClick: () -> Unit,
onRightClick: () -> Unit = {},
) {
var isCountVisible by remember { mutableStateOf(isImageVisible) }

// autoHideCount가 null이 아닐 때만 자동 숨김 로직 실행
LaunchedEffect(autoHideCount, count) {
when (autoHideCount) {
true -> {
if (count > 0) {
isCountVisible = true
delay(countDisplayDurationMs)
isCountVisible = false
}
}
false -> {
isCountVisible = true
}
null -> {
// 기존 동작 유지: isImageVisible 파라미터 사용
isCountVisible = isImageVisible
}
}
}

val bgColor = Brush.verticalGradient(
colors = listOf(
colors.Black,
Expand All @@ -54,15 +85,17 @@ fun GradationTopAppBar(
)
}

if (isImageVisible) {
CountingBar(
modifier = Modifier
.align(Alignment.Center),
content = stringResource(R.string.reading_user_num, count)
)
Column {
AnimatedVisibility(
visible = isCountVisible && count > 0
) {
CountingBar(
content = stringResource(R.string.reading_user_num, count)
)
}
}

IconButton(
/*IconButton(
onClick = onRightClick,
modifier = Modifier.align(Alignment.CenterEnd)
) {
Expand All @@ -71,7 +104,7 @@ fun GradationTopAppBar(
contentDescription = "More Options",
tint = Color.Unspecified
)
}
}*/
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ fun LogoTopAppBar(
val rightIcon = if (hasNotification) {
painterResource(R.drawable.ic_notice_yes)
} else {
painterResource(R.drawable.ic_notice)
painterResource(R.drawable.ic_notice_no)
}

Box(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.texthip.thip.ui.feed.screen

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.tween
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTapGestures
Expand Down Expand Up @@ -79,6 +83,7 @@ fun FeedCommentScreen(
onNavigateBack: () -> Unit = {},
onNavigateToFeedEdit: (Int) -> Unit = {},
onNavigateToUserProfile: (userId: Long) -> Unit = {},
onNavigateToBookDetail: (String) -> Unit = {},
feedDetailViewModel: FeedDetailViewModel = hiltViewModel(),
commentsViewModel: CommentsViewModel = hiltViewModel()
) {
Expand Down Expand Up @@ -223,7 +228,9 @@ fun FeedCommentScreen(
ActionBookButton(
bookTitle = feedDetail.bookTitle,
bookAuthor = feedDetail.bookAuthor,
onClick = {}
onClick = {
onNavigateToBookDetail(feedDetail.isbn)
}
)
}
Text(
Expand Down Expand Up @@ -398,17 +405,27 @@ fun FeedCommentScreen(
}
)
}
}

// 신고 완료 토스트
if (showToast) {
ToastWithDate(
message = "게시글 신고를 완료했어요.",
// 신고 완료 토스트
AnimatedVisibility(
visible = showToast,
enter = slideInVertically(
initialOffsetY = { -it },
animationSpec = tween(durationMillis = 2000)
),
exit = slideOutVertically(
targetOffsetY = { -it },
animationSpec = tween(durationMillis = 2000)
),
modifier = Modifier
.align(Alignment.TopCenter)
.padding(horizontal = 20.dp, vertical = 16.dp)
.zIndex(2f)
)
) {
ToastWithDate(
message = "게시글 신고를 완료했어요."
)
}
}

if (isBottomSheetVisible) {
Expand Down
Loading