Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
238547b
feat: 분석 플로우 내 음성 녹음 기능 및 일시정지 로직 구현
HamBeomJoon May 24, 2026
9282143
feat: GlobalEvent를 통한 상태바 스타일 제어 기능 구현
HamBeomJoon May 24, 2026
bde3fd8
refactor: 음성 녹음 화면 구조 개선 및 비즈니스 로직 리팩터링
HamBeomJoon May 24, 2026
da120a7
Merge remote-tracking branch 'origin/develop' into feat/#116-analysis…
HamBeomJoon May 26, 2026
c7f3c44
Merge remote-tracking branch 'origin/develop' into feat/#116-analysis…
HamBeomJoon May 26, 2026
b3ab3f8
feat: 분석 흐름 로직 개선 및 음성 녹음 UI 업데이트
HamBeomJoon May 26, 2026
7838c4b
feat: 분석 흐름 로직 개선 및 음성 녹음 UI 업데이트
HamBeomJoon May 26, 2026
7e099ff
feat: 발표 분석 재시작 및 단계별 네비게이션 기능 구현
HamBeomJoon May 27, 2026
5a8f929
refactor: 발표 분석 흐름 관련 로직 리팩터링 및 구조 개선
HamBeomJoon May 27, 2026
1e1a765
feat: 분석 시작 타입(녹음/파일 업로드) 구분 로직 구현
HamBeomJoon May 27, 2026
111d7d7
feat: 분석 재녹음 시 기존 대본 불러오기 기능 및 음성 녹음 화면 개선
HamBeomJoon May 29, 2026
9ef8a7d
feat: 분석 실패 처리 로직 강화 및 대본 파일 읽기 기능 추가
HamBeomJoon May 29, 2026
d786791
feat: 음성 녹음 화면의 상태바 스타일 동적 제어 로직 구현
HamBeomJoon May 29, 2026
e3aebc9
refactor: 분석 녹음 및 오디오 세션 관리 로직 개선
HamBeomJoon May 30, 2026
9dd38ad
Merge remote-tracking branch 'origin/develop' into feat/#116-analysis…
HamBeomJoon May 30, 2026
76a1d45
refactor: 분석 로직 개선 및 UI 구조 리팩터링
HamBeomJoon May 30, 2026
1372a52
refactor: 음성 녹음 상태바 스타일 라이프사이클 및 적용 시점 개선
HamBeomJoon May 30, 2026
58b619b
feat: 음성 녹음 화면 접근성 개선 및 테마 설정 수정
HamBeomJoon May 30, 2026
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
2 changes: 2 additions & 0 deletions Prezel/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@
.externalNativeBuild
.cxx
local.properties
.agents/
skills-lock.json
89 changes: 89 additions & 0 deletions Prezel/app/src/main/java/com/team/prezel/ui/PrezelApp.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.team.prezel.ui

import android.app.Activity
import android.content.Context
import android.content.ContextWrapper
import androidx.compose.animation.ContentTransform
import androidx.compose.animation.SharedTransitionLayout
import androidx.compose.animation.core.tween
Expand All @@ -8,19 +11,33 @@ import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.windowInsetsTopHeight
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
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.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.stringResource
import androidx.core.view.WindowCompat
import androidx.navigation3.runtime.EntryProviderScope
import androidx.navigation3.runtime.NavKey
import androidx.navigation3.runtime.entryProvider
import androidx.navigation3.ui.NavDisplay
import com.team.prezel.core.common.event.EdgeToEdgeStatusBarStyle
import com.team.prezel.core.common.event.GlobalEvent
import com.team.prezel.core.common.event.GlobalEventBus
import com.team.prezel.core.designsystem.component.PrezelNavigationScaffold
Expand Down Expand Up @@ -71,10 +88,12 @@ private fun PrezelAppContent(
) {
val navigator = LocalNavigator.current
val appDimmerState = LocalAppDimmerState.current
var statusBarStyle by remember { mutableStateOf(EdgeToEdgeStatusBarStyle.DEFAULT) }

ObserveGlobalEvents(
globalEventBus = globalEventBus,
navigateToSplash = { navigator.replaceRoot(SplashNavKey) },
onStatusBarStyleChange = { statusBarStyle = it },
)

Box(modifier = Modifier.fillMaxSize()) {
Expand All @@ -88,6 +107,7 @@ private fun PrezelAppContent(
}
}

EdgeToEdgeStatusBarBackground(style = statusBarStyle)
AppDimmerOverlay(isVisible = appDimmerState.isVisible, onDismiss = appDimmerState::dismiss)
}
}
Expand Down Expand Up @@ -139,20 +159,89 @@ private fun defaultPrezelNavTransition(): ContentTransform =
fadeIn(animationSpec = tween(durationMillis = 100)) togetherWith
fadeOut(animationSpec = tween(durationMillis = 100))

@Composable
private fun EdgeToEdgeStatusBarBackground(style: EdgeToEdgeStatusBarStyle) {
Spacer(
modifier = Modifier
.fillMaxWidth()
.windowInsetsTopHeight(WindowInsets.statusBars)
.background(style.toStatusBarColor()),
)
}

@Composable
private fun EdgeToEdgeStatusBarStyle.toStatusBarColor(): Color =
when (this) {
EdgeToEdgeStatusBarStyle.DEFAULT -> Color.Transparent
EdgeToEdgeStatusBarStyle.BG_REGULAR -> PrezelTheme.colors.bgRegular
EdgeToEdgeStatusBarStyle.BG_MEDIUM -> PrezelTheme.colors.bgMedium
}

@Composable
private fun ObserveGlobalEvents(
globalEventBus: GlobalEventBus,
navigateToSplash: () -> Unit,
onStatusBarStyleChange: (EdgeToEdgeStatusBarStyle) -> Unit,
) {
val context = LocalContext.current
val view = LocalView.current
val activity = context.findActivity()
val bgRegular = PrezelTheme.colors.bgRegular
val bgMedium = PrezelTheme.colors.bgMedium

LaunchedEffect(globalEventBus) {
globalEventBus.events.collect { event ->
when (event) {
GlobalEvent.ForceLogout -> navigateToSplash()
is GlobalEvent.ChangeEdgeToEdgeStatusBarStyle -> {
onStatusBarStyleChange(event.style)
activity?.applyEdgeToEdgeStatusBarStyle(
view = view,
style = event.style,
bgRegular = bgRegular,
bgMedium = bgMedium,
)
}

GlobalEvent.ResetEdgeToEdgeStatusBarStyle -> {
onStatusBarStyleChange(EdgeToEdgeStatusBarStyle.DEFAULT)
activity?.applyEdgeToEdgeStatusBarStyle(
view = view,
style = EdgeToEdgeStatusBarStyle.DEFAULT,
bgRegular = bgRegular,
bgMedium = bgMedium,
)
}
}
}
}
}

@Suppress("DEPRECATION")
private fun Activity.applyEdgeToEdgeStatusBarStyle(
view: android.view.View,
style: EdgeToEdgeStatusBarStyle,
bgRegular: Color,
bgMedium: Color,
) {
val insetsController = WindowCompat.getInsetsController(window, view)
val statusBarColor = when (style) {
EdgeToEdgeStatusBarStyle.DEFAULT -> Color.Transparent
EdgeToEdgeStatusBarStyle.BG_REGULAR -> bgRegular
EdgeToEdgeStatusBarStyle.BG_MEDIUM -> bgMedium
}.toArgb()

window.statusBarColor = statusBarColor
insetsController.isAppearanceLightStatusBars = true
}
Comment thread
HamBeomJoon marked this conversation as resolved.

private tailrec fun Context.findActivity(): Activity? =
when (this) {
is Activity -> this
is ContextWrapper -> baseContext.findActivity()
else -> null
}

@Composable
private fun PrezelNavigationScope.AppNavigationItems(
appState: PrezelAppState,
Expand Down
1 change: 1 addition & 0 deletions Prezel/core/audio/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ android {
dependencies {
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.compose.runtime)
implementation(libs.kotlinx.collections.immutable)
implementation(libs.kotlinx.coroutines.core)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ package com.team.prezel.core.audio
internal interface AudioRecorderSession {
fun start(): Result<Unit>

fun pause(): Result<Unit>

fun resume(): Result<Unit>

fun maxAmplitude(): Int

fun stop(elapsedSeconds: Int): Result<RecordedAudio>

fun reset()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ sealed interface AudioSessionState {
val elapsedSeconds: Int,
) : AudioSessionState

data class PausedRecording(
val elapsedSeconds: Int,
) : AudioSessionState

data class ReadyToPlay(
val source: AudioSource,
val positionSeconds: Int = 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,18 @@ internal class MediaRecorderSession @Inject constructor(
reset()
}

override fun pause(): Result<Unit> =
runCatching {
recorder?.pause() ?: error("Recorder not initialized")
}

override fun resume(): Result<Unit> =
runCatching {
recorder?.resume() ?: error("Recorder not initialized")
}

override fun maxAmplitude(): Int = recorder?.maxAmplitude ?: 0

override fun stop(elapsedSeconds: Int): Result<RecordedAudio> =
runCatching {
val file = currentAudioFile!!
Expand Down
Loading