feat(fantalk): 쓰기 입력 제한을 적용한다

This commit is contained in:
Yu Sung
2026-08-25 17:36:44 +09:00
parent 425099955b
commit cb3778a76f
5 changed files with 166 additions and 6 deletions

View File

@@ -27,6 +27,9 @@ Figma 참조:
- 팬레터 탭 empty 문구와 작성 버튼이 한국어로 하드코딩되어 앱 언어 설정에 맞게 표시되지 않는다.
- 내가 쓴 팬Talk의 `수정하기` 액션이 실제 수정 화면으로 연결되지 않는다.
- V2 화면에서 재사용할 수 있는 Figma 기준 액션 모달이 없어 입력 종료 안내 모달을 일관되게 표시하기 어렵다.
- 팬Talk 쓰기 화면의 취소 문구가 고정된 가로·세로 크기에 배치되어 언어에 따라 글자가 잘릴 수 있다.
- 팬Talk 쓰기 입력 영역에 placeholder가 없어 사용자가 입력 목적을 바로 알기 어렵다.
- 화면에 최대 글자 수 `500`이 표시되지만 실제 입력과 전송 가능 상태에는 상한이 적용되지 않는다.
## 3. Goals
- `CreatorChannelTab.fanTalk` 선택 시 팬Talk 탭 API를 호출하고 응답 데이터로 화면을 구성한다.
@@ -48,6 +51,10 @@ Figma 참조:
- 입력 종료 안내 모달은 V2 공용 액션 모달로 구현해 제목, 안내 문구, 버튼 1, 버튼 2의 label/action을 바꿔 재사용할 수 있게 한다.
- 팬Talk 작성과 수정은 이번에 작성하는 같은 쓰기 페이지에서 수행한다.
- 작성/수정 API는 기존 팬Talk API인 `ExplorerRepository.writeCheers``ExplorerRepository.modifyCheers`를 사용한다.
- 팬Talk 쓰기 화면의 취소 문구는 고정 `width: 64`, `height: 56`을 제거해 ko/en/ja에서 잘리지 않게 표시한다.
- 팬Talk 입력 영역은 ko/en/ja placeholder를 표시한다.
- 사용자는 500자까지 입력할 수 있고 501번째 이후 입력은 반영되지 않는다.
- 예외적으로 500자를 초과한 content가 주입되면 메시지 본문과 현재 글자 수를 `Color.red400`으로 표시하고 보내기 버튼을 비활성화한다.
## 4. Non-Goals
- 크리에이터 채널 공통 shell, header, sticky tab-bar 동작을 다시 설계하지 않는다.
@@ -201,6 +208,19 @@ data class CreatorChannelFanTalkReplyResponse(
- 키보드가 내려가도 입력 값과 보내기 버튼 활성화 상태는 유지한다.
- 입력 값이 없는 상태에서 취소 버튼을 터치하면 이전 화면으로 닫는다.
- 입력 값이 있는 상태에서 취소 버튼을 터치하면 입력 종료 안내 모달을 표시한다.
- 상단 내비게이션의 취소 `Text`에 적용된 고정 `width: 64`, `height: 56`만 제거한다.
- 상단 내비게이션 전체 높이 `56`과 보내기 capsule 높이 `44`는 유지한다.
- content가 비어 있을 때 입력 영역에 아래 placeholder를 표시한다.
- 한국어: `응원 메시지를 입력해 주세요.`
- 영어: `Enter a message of support.`
- 일본어: `応援メッセージを入力してください。`
- placeholder는 `I18n.CreatorChannelFanTalk`에서 ko/en/ja 값으로 관리하고 작성·수정 모드의 빈 content에 동일하게 적용한다.
- 글자 수는 Swift `String.count` 기준이며 최대 500자까지 허용한다.
- 사용자가 타이핑하거나 붙여넣어 500자를 초과하면 첫 500자만 content에 반영해 501번째 이후 문자는 입력되지 않게 한다.
- 500자인 content는 유효하며, 공백·줄바꿈만 있는 기존 비활성화 조건은 유지한다.
- 수정 초기값이나 외부 상태에서 500자를 초과한 content가 주입될 가능성은 별도 예외 상태로 처리한다.
- 예외 상태에서는 보내기 버튼을 비활성화하고, 입력 메시지 본문과 현재 글자 수를 `Color.red400`으로 표시한다.
- 예외 상태에서도 `/500` 최대 글자 수 표시는 기존 `Color.gray500`을 유지한다.
### 5.11 Reusable V2 action modal
- 입력 종료 안내 모달은 Figma `308:19046` 기준으로 표시한다.
@@ -246,6 +266,11 @@ data class CreatorChannelFanTalkReplyResponse(
- 수정 모드 진입 시 수정 대상 `fanTalkId`와 기존 글 content가 함께 전달된다.
- 수정 모드는 선택한 fanTalk의 기존 content를 입력값으로 표시한다.
- 수정 성공 후 팬Talk 탭 첫 페이지가 다시 조회된다.
- ko/en/ja에서 취소 문구가 잘리지 않고, 내비게이션 높이 `56`과 보내기 capsule 높이 `44`는 유지된다.
- content가 비어 있으면 앱 언어에 맞는 지정 placeholder가 표시되고 입력을 시작하면 사라진다.
- 500자는 입력·전송할 수 있고, 501번째 이후 타이핑과 붙여넣기 문자는 content에 반영되지 않는다.
- 예외적으로 500자를 초과한 content에서는 보내기 버튼이 비활성화되고 메시지 본문과 현재 글자 수가 `Color.red400`으로 표시된다.
- 공백·줄바꿈만 있는 content는 글자 수와 관계없이 보내기 버튼이 비활성화된다.
## 7. Technical Constraints
- 기능 변경은 `SodaLive/Sources/V2/CreatorChannel/**` 하위에서 해결한다.
@@ -260,6 +285,9 @@ data class CreatorChannelFanTalkReplyResponse(
- `CheersReportDialogView`는 신고 사유 선택 전용 UI이므로 이번 확인형 V2 popup dialog 전환 범위에서 제외한다.
- 신규 문구가 필요하면 `SodaLive/Sources/I18n/I18n.swift`에 ko/en/ja를 추가한다.
- Empty 문구와 `응원남기기` 버튼은 View에 직접 작성하지 않고 기존 크리에이터 채널 I18n 구조의 `pick(ko:en:ja:)` 값으로 관리한다.
- 쓰기 placeholder도 View에 직접 작성하지 않고 `I18n.CreatorChannelFanTalk``pick(ko:en:ja:)` 값으로 관리한다.
- 글자 수 제한은 Swift 표준 `String.count``prefix(_:)`를 사용하며 신규 dependency나 공용 입력 컴포넌트를 추가하지 않는다.
- 팬Talk 작성·수정 route와 API 계약은 변경하지 않는다.
- 프로젝트 설정 변경은 신규 Swift 파일 target 등록이 필요한 경우에만 수행한다.
## 8. Assumptions
@@ -284,3 +312,16 @@ data class CreatorChannelFanTalkReplyResponse(
- 2026-07-07: 사용자 후속 요청에 따라 팬Talk row 더보기의 삭제 확인 dialog는 팬Talk 탭 내부가 아니라 `CreatorChannelView` 상위 wrapping `ZStack`에서 표시한다. 삭제 확인 UI는 이번에 추가된 V2 공용 모달 `SodaV2ActionModal`을 사용하며, 팬Talk 리스트와 상세보기의 anchored context popup은 동일한 공용 컴포넌트와 동일한 `I18n` 문구를 사용한다. 신고 사유 선택 UI인 `CheersReportDialogView`는 기존 신고 플로우 재사용 범위로 유지하고 이번 확인형 V2 popup dialog 전환 범위에서 제외한다.
- 2026-08-14: 사용자 인터뷰로 팬레터 탭 empty 문구와 `응원남기기` 버튼의 ko/en/ja 값을 확정했다. 기존 작성 route와 내 채널 버튼 숨김 규칙은 유지하며 이번 작업에서는 Swift 구현을 수행하지 않는다.
- 2026-08-14: 사용자 요청에 따라 팬레터 탭 empty 작성 버튼은 `Color.gray800` 배경과 white 아이콘·텍스트를 사용하도록 확정했다. 홈 후원·팬레터 empty 버튼은 white/black, 후원 탭 empty 버튼은 기존 `Color.soda400`/white를 유지한다.
- 2026-08-25: 사용자 인터뷰로 500자까지 허용하고 501번째 이후 사용자 입력을 차단하며, 예외적인 500자 초과 상태에서는 메시지 본문과 현재 글자 수를 모두 붉게 표시하고 보내기 버튼을 비활성화하기로 확정했다.
- 2026-08-25: 상단 내비게이션에서는 취소 문구의 고정 `width: 64`, `height: 56`만 제거하고 내비게이션 높이 `56`과 보내기 capsule 높이 `44`는 유지하기로 확정했다.
- 2026-08-25: 기존 `CreatorChannelFanTalkWriteView`, `CreatorChannelFanTalkWriteViewModel`, `I18n.CreatorChannelFanTalk`을 확인했으며, 이번 작업에서는 요구사항 문서만 갱신하고 Swift 구현은 수행하지 않았다.
- 2026-08-25: Phase 12를 구현해 ko/en/ja placeholder, 500자 입력 제한, 500자 초과 예외 표시·전송 비활성화, 취소 문구의 고정 frame 제거를 적용했다. `§5.10`과 성공 기준의 관련 항목을 코드 및 정적 계약과 대조해 누락이 없음을 확인했다.
- 2026-08-25: Swift 499·500·501자 경계 검사, `git diff --check`, `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build`를 실행했고 `** BUILD SUCCEEDED **`를 확인했다. 사용자 요청에 따라 visual QA와 시뮬레이터 수동 검증은 수행하지 않았다.
## 11. Decision Log
| 날짜 | ID | 상태 | 결정 | 근거 | 영향 요구사항·계획 |
|---|---|---|---|---|---|
| 2026-08-25 | `DEC-FANTALK-WRITE-001` | 확정 | 500자까지 허용하고 501번째 이후 사용자 입력은 반영하지 않는다. 이미 500자를 초과한 content는 별도 예외 상태로 유지한다. | 사용자 인터뷰 A안 선택 | `§5.10`, Phase 12 |
| 2026-08-25 | `DEC-FANTALK-WRITE-002` | 확정 | 500자 초과 예외 상태에서는 메시지 본문과 현재 글자 수를 `Color.red400`으로 표시하고 보내기 버튼을 비활성화한다. | 사용자 인터뷰 C안 선택 | `§5.10`, Phase 12 |
| 2026-08-25 | `DEC-FANTALK-WRITE-003` | 확정 | 취소 문구의 고정 `width: 64`, `height: 56`만 제거하고 내비게이션 높이 `56`과 보내기 capsule 높이 `44`는 유지한다. | 사용자 인터뷰 A안 선택 | `§5.10`, Phase 12 |