발화 정확도 화면, 대본 일치율 화면 구현#148
Conversation
- 발화 정확도 및 대본 일치율 상세 분석을 위한 `AccuracyDetailScreen` 추가 - 오디오 재생과 연동된 단어별 분석 결과 표시 기능 구현 (MediaPlayer 사용) - 리포트 화면의 정확도 지표 카드 클릭 시 상세 화면으로 이동하는 로직 추가 - `WordAnalysisStatus` enum 도입 및 네트워크 응답 매퍼 수정 - 기존 리포트 관련 컴포넌트들을 `report` 패키지로 이동 및 구조 정리
…cript-match # Conflicts: # Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/navigation/ReportEntryBuilder.kt # Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/navigation/ReportInnerNavKey.kt # Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/report/AnalysisReportScreen.kt # Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/report/AnalysisReportViewModel.kt # Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/report/component/ReportBodyContent.kt # Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/report/component/ReportScreenLayout.kt # Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/report/component/body/AccuracySection.kt # Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/report/component/common/ReportMetricCards.kt # Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/report/contract/AnalysisReportUiIntent.kt # Prezel/feature/report/impl/src/main/res/values/strings.xml
- `AccuracyDetail` 화면의 데이터 로드 실패 시 스낵바 메시지 표시 로직 추가 - `ReportEntryBuilder` 내 내비게이션 호출 로직을 확장 함수로 분리하여 가독성 개선 - `ReportInnerNavKey.ScriptCorrection` 클래스에 `analysisResultId` 공통 인터페이스 적용 및 `Serializable` 어노테이션 추가 - `ReportMetricCards`의 불필요한 `noRippleClickable` 임포트 제거 - `AccuracyDetailUiEffect` 및 `AccuracyDetailUiMessage` 정의를 통한 에러 핸들링 구조화
- 분석 단위를 `WordAnalysisDetail`에서 `SentenceAnalysisDetail`로 변경하여 문장 단위 피드백 및 UI 구현 - 문장 내 개별 단어의 분석 상태를 하이라이트하여 표시하는 `SentenceAnalysisCard` 컴포넌트 추가 - UI 상태 관리를 위한 `SentenceAnalysisUiModel` 및 `WordAnalysisUiModel` 정의 - 도메인 모델 및 네트워크 응답 DTO에 문장 상세 정보(`sentenceDetails`) 필드 추가 - `WordAnalysisDetail`에서 더 이상 사용하지 않는 `description` 필드 제거 - 컬렉션의 안정성을 위해 `kotlinx.collections.immutable` 의존성 추가 및 `ImmutableList` 적용 - `AccuracyDetailScreen` 및 관련 컴포넌트의 데이터 흐름을 문장 모델 중심으로 리팩터링
- `RemoteAudioPlaybackState` 구현을 통해 `MediaPlayer`의 준비 상태 및 에러 핸들링 로직 강화 - UI 플레이어 상태와 실제 오디오 재생 위치 간의 동기화 로직 추가 (`SEEK_SYNC_THRESHOLD_MILLIS` 기준) - 분석 데이터 유무에 따라 바텀 시트의 `peekHeight`를 동적으로 조절하는 기능 구현 - `SentenceAnalysisUiModel`의 상태 판정 로직 개선 및 `hasSpeechAccuracyStatus` 등 신규 필드 추가 - `AccuracyDetailViewModel`의 데이터 요청 로직을 `onSuccess`/`onFailure` 구조로 리팩터링 - 바텀 시트 내부 레이아웃 구성 및 스크롤 동작 최적화
|
Warning Review limit reached
More reviews will be available in 36 minutes and 7 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
📝 Walkthrough발화 정확도/대본 일치 상세 화면 구현문장 단위 분석 데이터 구조로 재설계하고, 정확도 상세 화면의 전체 MVVM 아키텍처를 구현했으며, 원격 오디오 재생 동기화와 UI 컴포넌트 렌더링을 포함하고, 기존 리포트 화면과 네비게이션으로 통합합니다. 변경사항데이터 모델 구조화 및 네트워크 스키마 업데이트
정확도 상세 화면 MVVM 및 상태 관리
원격 오디오 재생 관리
정확도 상세 화면 UI 구성
UI 모델 및 데이터 매핑
네비게이션 통합
지역화 문자열
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Prezel/core/model/build.gradle.kts`:
- Line 6: The build.gradle.kts currently declares
implementation(libs.kotlinx.collections.immutable) but PresentationWordDetail
(sentenceDetails/wordDetails) exposes ImmutableList in its public API, so either
the dependency must be published as api or the convention must be updated to
ensure api propagation; update the project as follows: (1) Decide whether the
module should expose ImmutableList - if yes, change implementation(...) to
api(libs.kotlinx.collections.immutable) in Prezel/core/model/build.gradle.kts;
(2) If the prezel.jvm.library convention does not configure apiElements (it
currently only applies org.jetbrains.kotlin.jvm), update the convention
(Prezel/build-logic/convention) to apply the java-library plugin or otherwise
configure API dependency propagation so api(...) has an effect; (3) After
updating the convention, switch implementation to api in build.gradle.kts and
run build to verify the ImmutableList type is available to consumers; if you
choose not to expose ImmutableList, instead make sentenceDetails/wordDetails use
internal/private types or map to public types so implementation scope remains
correct.
In
`@Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/accuracydetail/AccuracyDetailScreen.kt`:
- Around line 202-213: initialItems is remembered only by markerSentenceDetails
while it depends on selectedTab too, causing stale markerType after tab
switches; update the remember call in AccuracyDetailScreen so it includes
selectedTab (e.g., remember(markerSentenceDetails, selectedTab) { ... }) so
PrezelPlayerItem.Marker mapping (using selectedTab to choose
speechAccuracyStatus.toMarkerType() vs scriptMatchStatus.toMarkerType()) is
recomputed when the tab changes.
In
`@Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/accuracydetail/component/ScriptDetailList.kt`:
- Around line 42-54: The empty-state text is always using the speech-only string
even when selectedTab == SCRIPT_MATCH; update the branch in ScriptDetailList
(where sentenceDetails.isNotEmpty() is checked and
SentenceAnalysisCard/EmptyDetailText are used) to choose the EmptyDetailText
message based on selectedTab (e.g., use a when(selectedTab) to call
stringResource(R.string.feature_report_impl_script_detail_empty_speech) for
speech tab and the appropriate stringResource for SCRIPT_MATCH and any other
tabs), leaving the existing SentenceAnalysisCard usage (detail, highlighted,
showStatusChip, highlightWordDetails, status) unchanged.
In
`@Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/accuracydetail/component/SentenceAnalysisCard.kt`:
- Around line 181-192: The UNKNOWN branch in WordAnalysisStatus.statusLabel()
currently returns the raw enum value (WordAnalysisStatus.UNKNOWN -> value);
change it to return a localized string resource instead (e.g.,
WordAnalysisStatus.UNKNOWN ->
stringResource(R.string.feature_report_impl_script_detail_status_unknown)), and
add the corresponding entry in strings.xml (and provide translations) so UNKNOWN
is shown via resources rather than the raw enum value.
In
`@Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/accuracydetail/model/SentenceAnalysisUiModel.kt`:
- Around line 46-53: The mapping misclassifies MISPRONUNCIATION as a
script-match issue; update the two extension getters so MISPRONUNCIATION is
removed from WordAnalysisStatus.isScriptMatchIssue and added to
WordAnalysisStatus.isSpeechAccuracyIssue: change isScriptMatchIssue to only
include INSERTION and OMISSION, and change isSpeechAccuracyIssue to include
STUTTER and MISPRONUNCIATION (adjust the boolean expressions in the respective
getters).
In
`@Prezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/accuracydetail/RemoteAudioPlaybackState.kt`:
- Around line 88-115: The preparePlayer() path can leak a MediaPlayer if an
exception is thrown before assigning the new instance to the mediaPlayer field;
modify RemoteAudioPlaybackState.preparePlayer so you create the MediaPlayer into
a local val (e.g., val player = MediaPlayer()), use that local for
setOnPreparedListener/setDataSource/prepareAsync/etc., and in the
runCatching.onFailure block call player.release() for that local instance (but
avoid releasing the field mediaPlayer which should only be released elsewhere);
after successful creation assign mediaPlayer = player as the current instance.
In `@Prezel/feature/report/impl/src/main/res/values/strings.xml`:
- Line 65: The empty-state text for the script tab is hard-coded to the
speech-only string feature_report_impl_script_detail_empty_speech; add a new
string resource (e.g., feature_report_impl_script_detail_empty_script with the
appropriate script-specific text) and update the UI logic in ScriptDetailList to
branch on the active tab type (script vs speech/mismatch tab) and select the
correct string resource (use feature_report_impl_script_detail_empty_script for
the script tab and keep feature_report_impl_script_detail_empty_speech for the
speech tab); ensure the code paths that currently reference
feature_report_impl_script_detail_empty_speech are replaced or conditionalized
to use the new key when the script tab is active.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: c83b1150-1db5-4c3c-a9fc-7ada793f1272
📒 Files selected for processing (28)
Prezel/core/data/build.gradle.ktsPrezel/core/data/src/main/java/com/team/prezel/core/data/mapper/PresentationMapper.ktPrezel/core/model/build.gradle.ktsPrezel/core/model/src/main/java/com/team/prezel/core/model/presentation/PresentationWordDetail.ktPrezel/core/network/src/main/java/com/team/prezel/core/network/model/presentation/PresentationWordDetailResponse.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/accuracydetail/AccuracyDetailScreen.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/accuracydetail/AccuracyDetailViewModel.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/accuracydetail/RemoteAudioPlaybackState.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/accuracydetail/component/AccuracyDetailPlayerSheet.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/accuracydetail/component/AccuracyDetailTopAppBar.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/accuracydetail/component/ScriptDetailList.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/accuracydetail/component/SentenceAnalysisCard.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/accuracydetail/contract/AccuracyDetailUiEffect.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/accuracydetail/contract/AccuracyDetailUiIntent.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/accuracydetail/contract/AccuracyDetailUiState.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/accuracydetail/model/AccuracyDetailUiMessage.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/accuracydetail/model/SentenceAnalysisUiModel.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/navigation/ReportEntryBuilder.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/navigation/ReportInnerNavKey.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/report/AnalysisReportScreen.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/report/AnalysisReportViewModel.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/report/component/ReportBodyContent.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/report/component/ReportScreenLayout.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/report/component/body/AccuracySection.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/report/component/common/ReportMetricCards.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/report/contract/AnalysisReportUiEffect.ktPrezel/feature/report/impl/src/main/java/com/team/prezel/feature/report/impl/report/contract/AnalysisReportUiIntent.ktPrezel/feature/report/impl/src/main/res/values/strings.xml
- `WordAnalysisStatus.MISPRONUNCIATION`을 대본 일치 이슈에서 발음 정확도 이슈로 재분류 - 선택된 탭 종류에 따라 빈 화면 메시지가 다르게 표시되도록 `emptyDetailTextResId` 로직 추가 - `AccuracyDetailScreen`에서 탭 전환 시 플레이어 마커가 정상적으로 갱신되도록 `remember` 종속성 추가 - `WordAnalysisStatus.UNKNOWN` 상태에 하드코딩된 값 대신 문자열 리소스 적용 - `RemoteAudioPlaybackState`에서 `MediaPlayer` 초기화 실패 시 `release()`를 호출하여 자원 누수 방지 및 안정성 강화
📌 작업 내용
분석 리포트 정확도 상세 화면 추가
리포트 화면의
발화,대본 일치율카드 클릭 시 정확도 상세 화면으로 이동하도록 연결했습니다.정확도 상세 화면에서 발화/대본 일치율 탭을 제공하고, 문장 단위 분석 결과를 표시합니다.
문장별 시간, 상태 chip, 피드백, 단어 단위 하이라이트를 렌더링합니다.
/recording/analyze/{analysisResultId}/words응답을 문장 기반 구조로 변경했습니다.상세 화면 하단 bottom sheet에 오디오 플레이어를 추가했습니다.
🧩 관련 이슈
📸 스크린샷
Summary by CodeRabbit
새로운 기능