-
Notifications
You must be signed in to change notification settings - Fork 0
[Feat] 통화 기록 UI 및 음성파일 재생 기능 구현 & 홈 화면 팝업창 구현 #36
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
Merged
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
143b597
refactor: #7 홈 데이터 매퍼 분리
JiwonLee42 9a9fddf
refactor: #7 홈 데이터 흐름을 Repository로 전환
JiwonLee42 435a7b9
feat: #7 홈 상태와 이벤트 모델 구성
JiwonLee42 fedb714
feat: #7 캐릭터 및 통화 팝업 추가
JiwonLee42 739fec3
feat: #7 시간 변경 범위와 반올림 로직 보완
JiwonLee42 53fa248
feat: #7 홈 화면 상태와 팝업 동작 연결
JiwonLee42 d998478
feat: #10 통화기록 조회 상태와 데이터 변환 추가
JiwonLee42 61daa5f
feat: #10 통화 정보와 대화 스크립트 UI 추가
JiwonLee42 ddd6421
feat: #10 Media3 통화 녹음 플레이어 구현
JiwonLee42 5a2a3d5
feat: #10 통화기록 상세 화면 내비게이션 연결
JiwonLee42 c4a9848
refactor: #7 홈 도메인 모델 파일 통합
JiwonLee42 916edb3
refactor: #10 통화기록 도메인 모델 파일 통합
JiwonLee42 e4f84ba
refactor: #7 #10 홈과 통화기록 Repository 분리
JiwonLee42 4420561
feat: #10 통화기록 로딩과 재생 상태 개선
JiwonLee42 e7e858b
style: #7 홈 헤더 패딩 적용
JiwonLee42 e7c6211
Merge branch 'develop' into feat/#7-home-ui
JiwonLee42 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
core/data/src/main/java/kr/co/call/data/mapper/CallTranscriptMapper.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package kr.co.call.data.mapper | ||
|
|
||
| import kr.co.call.domain.model.home.CallTranscript | ||
| import kr.co.call.network.dto.CallTranscriptDto | ||
| import kr.co.call.network.dto.CallTranscriptResultDto | ||
|
|
||
| internal fun CallTranscriptResultDto.toDomain(): List<CallTranscript> = | ||
| content.map { transcript -> transcript.toDomain() } | ||
|
|
||
| private fun CallTranscriptDto.toDomain(): CallTranscript = | ||
| CallTranscript( | ||
| content = content, | ||
| speaker = speaker.toDomainSpeaker(), | ||
| ) | ||
|
|
||
| private fun String.toDomainSpeaker(): CallTranscript.Speaker = | ||
| when (this) { | ||
| "사용자", "USER" -> CallTranscript.Speaker.USER | ||
| "AI" -> CallTranscript.Speaker.AI | ||
| else -> error("지원하지 않는 화자입니다: $this") | ||
| } |
12 changes: 12 additions & 0 deletions
12
core/data/src/main/java/kr/co/call/data/mapper/HomeMapper.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package kr.co.call.data.mapper | ||
|
|
||
| import kr.co.call.domain.model.home.HomeSummary | ||
| import kr.co.call.network.dto.HomeSummaryDto | ||
|
|
||
| internal fun HomeSummaryDto.toDomain(): HomeSummary = | ||
| HomeSummary( | ||
| firstName = firstName, | ||
| relationshipDays = relationshipDays, | ||
| totalCallCount = totalCallCount, | ||
| callStreakDays = callStreakDays, | ||
| ) |
22 changes: 22 additions & 0 deletions
22
core/data/src/main/java/kr/co/call/data/mapper/ReservationMapper.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| package kr.co.call.data.mapper | ||
|
|
||
| import java.time.LocalDateTime | ||
| import kr.co.call.domain.model.home.CallReservation | ||
| import kr.co.call.domain.model.home.CallReservations | ||
| import kr.co.call.network.dto.ReservationDto | ||
| import kr.co.call.network.dto.ReservationListDto | ||
|
|
||
| internal fun ReservationListDto.toDomain(): CallReservations = | ||
| CallReservations( | ||
| totalCount = count, | ||
| items = content.map { reservation -> reservation.toDomain() }, | ||
| ) | ||
|
|
||
| private fun ReservationDto.toDomain(): CallReservation = | ||
| CallReservation( | ||
| id = callReservationId, | ||
| characterId = characterId, | ||
| firstName = firstName, | ||
| imageUrl = imageUrl, | ||
| scheduledAt = LocalDateTime.parse(scheduledAt), | ||
| ) |
62 changes: 62 additions & 0 deletions
62
core/data/src/main/java/kr/co/call/data/repositoryImpl/CallRecordMockRepository.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| package kr.co.call.data.repositoryImpl | ||
|
|
||
| import java.time.LocalDateTime | ||
| import javax.inject.Inject | ||
| import kr.co.call.domain.model.home.CallInfo | ||
| import kr.co.call.domain.model.home.CallTranscript | ||
| import kr.co.call.domain.repository.CallRecordRepository | ||
|
|
||
| class CallRecordMockRepository @Inject constructor() : CallRecordRepository { | ||
|
|
||
| override suspend fun getCallInfo(callId: Long): Result<CallInfo> { | ||
| if (callId !in 1L..20L) { | ||
| return callNotFound() | ||
| } | ||
|
|
||
| return Result.success( | ||
| CallInfo( | ||
| callId = callId, | ||
| title = "출근 준비와 아침 일정 이야기", | ||
| calledAt = LocalDateTime.of(2026, 6, 27, 7, 31), | ||
| characterName = if (callId % 2L == 1L) "민준" else "동휘", | ||
| recordingUrl = | ||
| "https://storage.googleapis.com/exoplayer-test-media-0/play.mp3", | ||
| durationMillis = 0L, | ||
| ), | ||
| ) | ||
| } | ||
|
|
||
| override suspend fun getCallScript( | ||
| callId: Long, | ||
| ): Result<List<CallTranscript>> { | ||
| if (callId !in 1L..20L) { | ||
| return callNotFound() | ||
| } | ||
|
|
||
| return Result.success( | ||
| listOf( | ||
| CallTranscript( | ||
| content = "여보세요", | ||
| speaker = CallTranscript.Speaker.USER, | ||
| ), | ||
| CallTranscript( | ||
| content = "잘 일어났어? 목소리 아직 잠긴 것 같은데.", | ||
| speaker = CallTranscript.Speaker.AI, | ||
| ), | ||
| CallTranscript( | ||
| content = "응 방금 일어나 준비하고 있었어", | ||
| speaker = CallTranscript.Speaker.USER, | ||
| ), | ||
| CallTranscript( | ||
| content = "오늘 출근이지? 몸은 좀 괜찮아? 피곤해 보여.", | ||
| speaker = CallTranscript.Speaker.AI, | ||
| ), | ||
| ), | ||
| ) | ||
| } | ||
|
|
||
| private fun <T> callNotFound(): Result<T> = | ||
| Result.failure( | ||
| IllegalArgumentException("통화 기록을 찾을 수 없습니다."), | ||
| ) | ||
| } |
21 changes: 21 additions & 0 deletions
21
core/data/src/main/java/kr/co/call/data/repositoryImpl/CallRecordRepositoryImpl.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package kr.co.call.data.repositoryImpl | ||
|
|
||
| import javax.inject.Inject | ||
| import kr.co.call.domain.model.home.CallInfo | ||
| import kr.co.call.domain.model.home.CallTranscript | ||
| import kr.co.call.domain.repository.CallRecordRepository | ||
|
|
||
| class CallRecordRepositoryImpl @Inject constructor() : CallRecordRepository { | ||
|
|
||
| override suspend fun getCallInfo(callId: Long): Result<CallInfo> = | ||
| unsupportedApi() | ||
|
|
||
| override suspend fun getCallScript( | ||
| callId: Long, | ||
| ): Result<List<CallTranscript>> = unsupportedApi() | ||
|
|
||
| private fun <T> unsupportedApi(): Result<T> = | ||
| Result.failure( | ||
| UnsupportedOperationException("통화 기록 서버 API가 아직 연결되지 않았습니다."), | ||
| ) | ||
| } |
139 changes: 139 additions & 0 deletions
139
core/data/src/main/java/kr/co/call/data/repositoryImpl/HomeMockRepository.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| package kr.co.call.data.repositoryImpl | ||
|
|
||
| import java.time.LocalDateTime | ||
| import javax.inject.Inject | ||
| import kr.co.call.domain.exception.CharacterChangeUnavailableException | ||
| import kr.co.call.domain.model.home.CallHistory | ||
| import kr.co.call.domain.model.home.CallReservation | ||
| import kr.co.call.domain.model.home.CallReservations | ||
| import kr.co.call.domain.model.home.HomeCharacter | ||
| import kr.co.call.domain.model.home.HomeSummary | ||
| import kr.co.call.domain.repository.HomeRepository | ||
|
|
||
| class HomeMockRepository @Inject constructor() : HomeRepository { | ||
|
|
||
| private var characters = listOf( | ||
| HomeCharacter( | ||
| id = 1L, | ||
| name = "민준", | ||
| relationshipDays = 30, | ||
| imageUrl = null, | ||
| isMain = true, | ||
| ), | ||
| HomeCharacter( | ||
| id = 2L, | ||
| name = "동휘", | ||
| relationshipDays = 12, | ||
| imageUrl = null, | ||
| isMain = false, | ||
| ), | ||
| ) | ||
|
|
||
| private var reservations = CallReservations( | ||
| totalCount = 1, | ||
| items = listOf( | ||
| CallReservation( | ||
| id = 3L, | ||
| characterId = 1L, | ||
| firstName = "민준", | ||
| imageUrl = null, | ||
| scheduledAt = LocalDateTime.of(2026, 6, 30, 21, 0), | ||
| ), | ||
| ), | ||
| ) | ||
|
|
||
| override suspend fun getCharacters(): Result<List<HomeCharacter>> = | ||
| Result.success(characters) | ||
|
|
||
| override suspend fun getReservations(): Result<CallReservations> = | ||
| Result.success(reservations) | ||
|
|
||
| override suspend fun getCallHistories(): Result<List<CallHistory>> = | ||
| Result.success( | ||
| List(20) { index -> | ||
| CallHistory( | ||
| callId = (index + 1).toLong(), | ||
| characterName = if (index % 2 == 0) "민준" else "동휘", | ||
| aiSummary = if (index % 2 == 0) { | ||
| "오늘 하루와 퇴근 후 일상 이야기" | ||
| } else { | ||
| "몸살 감기 기운과 걱정해주는 이야기" | ||
| }, | ||
| startedAt = LocalDateTime.of( | ||
| 2026, | ||
| 6, | ||
| (28 - index).coerceAtLeast(1), | ||
| 23, | ||
| 2, | ||
| ), | ||
| isOutgoing = index % 2 == 0, | ||
| isMissed = index % 4 == 3, | ||
| ) | ||
| }, | ||
| ) | ||
|
|
||
| override suspend fun getSummary(): Result<HomeSummary> = | ||
| Result.success( | ||
| HomeSummary( | ||
| firstName = "수현", | ||
| relationshipDays = 30, | ||
| totalCallCount = 24, | ||
| callStreakDays = 12, | ||
| ), | ||
| ) | ||
|
|
||
| override suspend fun changeReservationTime( | ||
| reservationId: Long, | ||
| scheduledAt: LocalDateTime, | ||
| ): Result<CallReservations> { | ||
| val hasReservation = reservations.items.any { reservation -> | ||
| reservation.id == reservationId | ||
| } | ||
| if (!hasReservation) { | ||
| return Result.failure( | ||
| IllegalArgumentException("변경할 예약을 찾을 수 없습니다."), | ||
| ) | ||
| } | ||
|
|
||
| reservations = reservations.copy( | ||
| items = reservations.items.map { reservation -> | ||
| if (reservation.id == reservationId) { | ||
| reservation.copy(scheduledAt = scheduledAt) | ||
| } else { | ||
| reservation | ||
| } | ||
| }, | ||
| ) | ||
|
|
||
| return Result.success(reservations) | ||
| } | ||
|
|
||
| override suspend fun changeMainCharacter( | ||
| characterId: Long, | ||
| ): Result<List<HomeCharacter>> { | ||
| val hasCharacter = characters.any { character -> | ||
| character.id == characterId | ||
| } | ||
| if (!hasCharacter) { | ||
| return Result.failure( | ||
| IllegalArgumentException("변경할 캐릭터를 찾을 수 없습니다."), | ||
| ) | ||
| } | ||
|
|
||
| return Result.failure(CharacterChangeUnavailableException()) | ||
| } | ||
|
|
||
| override suspend fun startCall(characterId: Long): Result<Unit> { | ||
| val isMainCharacter = characters.any { character -> | ||
| character.id == characterId && character.isMain | ||
| } | ||
|
|
||
| return if (isMainCharacter) { | ||
| Result.success(Unit) | ||
| } else { | ||
| Result.failure( | ||
| IllegalStateException("메인 캐릭터와만 통화할 수 있습니다."), | ||
| ) | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
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.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
홈→통화 기록 전환 화면 자료를 PR에 첨부해 주세요.
PR 설명에 이 변경 흐름을 확인할 스크린샷 또는 화면 녹화가 없습니다. As per coding guidelines, "
*Screen.kt변경 시 스크린샷 또는 화면 녹화가 첨부되었는지 확인하고 없으면 경고한다" 규칙에 따른 사항입니다.🤖 Prompt for AI Agents
Source: Coding guidelines
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.
이거왜안했엇!!!!!!
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.
@codebidoof맞습니다, 이건 제가 코드 변경과 별개로 PR 설명의 화면 자료 첨부 여부를 체크하는 가이드라인 때문에 잡은 항목이에요. 이번 PR에서HomeScreen.kt와CallRecordScreen.kt가 변경됐는데, 설명에 홈 → 통화 기록 진입 및 뒤로가기 흐름을 보여주는 스크린샷/영상이 없어서 경고됐습니다.번거롭게 해서 죄송합니다 🙇 PR 설명에 해당 화면 자료만 첨부하면 충분합니다.
🐰💦