Skip to content

Commit

Permalink
Merge pull request #220 from SWM-KAWAI-MANS/release/v1.2.0
Browse files Browse the repository at this point in the history
Release/v1.2.0
  • Loading branch information
nohjunh authored Oct 4, 2023
2 parents 9346563 + c72dee2 commit 3acd13e
Show file tree
Hide file tree
Showing 9 changed files with 170 additions and 3 deletions.
4 changes: 2 additions & 2 deletions buildSrc/src/main/java/Configurations.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ object Configurations {
const val MIN_SDK_VERSION = 26
const val TARGET_SDK_VERSION = 33
private const val MAJOR_VERSION = 1
private const val MINOR_VERSION = 1
private const val MINOR_VERSION = 2
private const val PATCH_VERSION = 0
const val VERSION_NAME = "$MAJOR_VERSION.$MINOR_VERSION.$PATCH_VERSION"
const val VERSION_CODE = 21
const val VERSION_CODE = 22
// kotlinCompilerExtensionVersion
const val COMPOSE = "1.4.5"
}
1 change: 1 addition & 0 deletions core/common/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.VIBRATE" />
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package online.partyrun.partyrunapplication.core.common.util

import android.content.Context
import android.speech.tts.TextToSpeech
import android.speech.tts.UtteranceProgressListener
import java.util.Locale
import java.util.UUID

class TTSManager(context: Context, onInitSuccess: (TTSManager) -> Unit) {
private var textToSpeech: TextToSpeech? = null

init {
textToSpeech = TextToSpeech(context) { status ->
if (status == TextToSpeech.SUCCESS) {
textToSpeech?.run {
language = Locale.KOREA
setSpeechRate(1.3f)
onInitSuccess(this@TTSManager)
}
}
}
}

/*
* UUID를 사용하여 id를 고유하게 생성 -> 메시지를 연속으로 발화할 때 중복되는 utteranceId 문제 방지
*/
fun speak(text: String, shouldShutdownAfterSpeaking: Boolean = false) {
val utteranceId = UUID.randomUUID().toString()
if (shouldShutdownAfterSpeaking) {
shutdownAfterSpeaking(utteranceId)
}
textToSpeech?.speak(
text,
TextToSpeech.QUEUE_ADD,
null,
utteranceId
)
}

private fun shutdownAfterSpeaking(utteranceId: String) {
textToSpeech?.setOnUtteranceProgressListener(object : UtteranceProgressListener() {
override fun onStart(utteranceId: String?) {
// speaking
}

override fun onError(utteranceId: String?) {
// speaking error
}

override fun onDone(expectedUtteranceId: String?) {
if (expectedUtteranceId == utteranceId) {
shutdown()
}
}
})
}

fun shutdown() {
textToSpeech?.shutdown()
textToSpeech = null
}
}

fun speakTTS(context: Context, message: String) {
TTSManager(context) { manager ->
manager.speak(message, shouldShutdownAfterSpeaking = true)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package online.partyrun.partyrunapplication.core.common.util

import android.content.Context
import android.os.Build
import android.os.VibrationEffect
import android.os.Vibrator
import android.os.VibratorManager

class VibrateDeviceManager(context: Context) {
private val vibrator: Vibrator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val vibratorManager =
context.getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
vibratorManager.defaultVibrator
} else {
@Suppress("DEPRECATION")
context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
}

fun vibrateFor(time: Long) {
vibrator.vibrate(
VibrationEffect.createOneShot(
time,
VibrationEffect.DEFAULT_AMPLITUDE,
)
)
}
}

fun vibrateSingle(context: Context) {
val vibrator = VibrateDeviceManager(context)
vibrator.vibrateFor(200)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package online.partyrun.partyrunapplication.feature.my_page.profile

import androidx.activity.OnBackPressedCallback
import androidx.activity.compose.LocalOnBackPressedDispatcherOwner
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
Expand Down Expand Up @@ -28,8 +30,10 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
Expand All @@ -38,6 +42,7 @@ import androidx.compose.ui.focus.FocusManager
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.platform.SoftwareKeyboardController
import androidx.compose.ui.res.painterResource
Expand Down Expand Up @@ -112,6 +117,10 @@ fun Content(
val keyboardController = LocalSoftwareKeyboardController.current
val focusManager = LocalFocusManager.current

ProfileBackNavigationHandler(
navigateToMyPage = navigateToMyPage
)

LaunchedEffect(profileSnackbarMessage) {
if (profileSnackbarMessage.isNotEmpty()) {
onShowSnackbar(profileSnackbarMessage)
Expand Down Expand Up @@ -407,3 +416,26 @@ private fun NickNameSupportingText(profileUiState: ProfileUiState) {
}
}
}

@Composable
fun ProfileBackNavigationHandler(
navigateToMyPage: () -> Unit
) {
val onBackPressedDispatcher = LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher
val lifecycleOwner = LocalLifecycleOwner.current
val onBackPressedCallback = remember {
object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
navigateToMyPage()
}
}
}

// lifecycleOwner와 backDispatcher가 변경될 때마다 실행
DisposableEffect(lifecycleOwner, onBackPressedDispatcher) {
onBackPressedDispatcher?.addCallback(lifecycleOwner, onBackPressedCallback)
onDispose {
onBackPressedCallback.remove()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import kotlinx.coroutines.delay
import online.partyrun.partyrunapplication.core.common.util.speakTTS
import online.partyrun.partyrunapplication.core.common.util.vibrateSingle
import online.partyrun.partyrunapplication.core.model.single.SingleRunnerDisplayStatus
import online.partyrun.partyrunapplication.feature.running.R
import online.partyrun.partyrunapplication.feature.running.running.component.ControlPanelColumn
Expand All @@ -45,6 +47,7 @@ import online.partyrun.partyrunapplication.feature.running.running.component.Run
import online.partyrun.partyrunapplication.feature.running.running.component.SingleRunnerMarker
import online.partyrun.partyrunapplication.feature.running.running.component.TrackDistanceDistanceBox
import online.partyrun.partyrunapplication.feature.running.running.component.trackRatio
import online.partyrun.partyrunapplication.feature.running.single.RunningServiceState
import online.partyrun.partyrunapplication.feature.running.single.SingleContentUiState
import online.partyrun.partyrunapplication.feature.running.single.SingleContentViewModel

Expand All @@ -55,6 +58,15 @@ fun SingleRunningScreen(
openRunningExitDialog: MutableState<Boolean>,
singleContentViewModel: SingleContentViewModel = hiltViewModel()
) {
val context = LocalContext.current

if (singleContentUiState.runningServiceState == RunningServiceState.STARTED) {
LaunchedEffect(Unit) {
vibrateSingle(context)
speakTTS(context, context.getString(R.string.tts_running_start))
}
}

Scaffold(
modifier = Modifier.fillMaxSize()
) { paddingValues ->
Expand Down Expand Up @@ -136,6 +148,7 @@ fun SingleRunningScreen(
horizontalAlignment = Alignment.CenterHorizontally
) {
ControlPanelColumn(
context = context,
singleContentUiState = singleContentUiState,
singleContentViewModel = singleContentViewModel,
openRunningExitDialog = openRunningExitDialog
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
Expand All @@ -38,6 +39,8 @@ fun SingleUserPausedScreen(
singleContentViewModel: SingleContentViewModel = hiltViewModel(),
openRunningExitDialog: MutableState<Boolean>,
) {
val context = LocalContext.current

Column(
modifier = Modifier.fillMaxSize()
) {
Expand Down Expand Up @@ -77,7 +80,12 @@ fun SingleUserPausedScreen(
verticalArrangement = Arrangement.SpaceEvenly,
horizontalAlignment = Alignment.CenterHorizontally
) {
ControlPanelColumn(singleContentUiState, singleContentViewModel, openRunningExitDialog)
ControlPanelColumn(
context,
singleContentUiState,
singleContentViewModel,
openRunningExitDialog
)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package online.partyrun.partyrunapplication.feature.running.running.component

import android.content.Context
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import online.partyrun.partyrunapplication.core.common.util.speakTTS
import online.partyrun.partyrunapplication.core.common.util.vibrateSingle
import online.partyrun.partyrunapplication.feature.running.R
import online.partyrun.partyrunapplication.feature.running.running.FixedWidthTimeText
import online.partyrun.partyrunapplication.feature.running.single.SingleContentUiState
Expand All @@ -15,6 +18,7 @@ import online.partyrun.partyrunapplication.feature.running.single.getTimeCompone

@Composable
fun ControlPanelColumn(
context: Context,
singleContentUiState: SingleContentUiState,
singleContentViewModel: SingleContentViewModel,
openRunningExitDialog: MutableState<Boolean>
Expand All @@ -26,12 +30,17 @@ fun ControlPanelColumn(
FixedWidthTimeText(hours, minutes, seconds)
}
Spacer(modifier = Modifier.size(5.dp))

RunControlPanel(
pausedState = singleContentUiState.runningServiceState,
pauseAction = {
speakTTS(context, context.getString(R.string.tts_running_pause))
vibrateSingle(context)
singleContentViewModel.pauseSingleRunningService(isUserPaused = true)
},
resumeAction = {
speakTTS(context, context.getString(R.string.tts_running_resume))
vibrateSingle(context)
singleContentViewModel.resumeSingleRunningService()
},
stopAction = {
Expand Down
4 changes: 4 additions & 0 deletions feature/running/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,9 @@
<string name="location_permission_description">정확한 GPS 신호를 통한 러닝 추적을 위해 위치 정보 액세스를 허용해주세요.</string>
<string name="location_permission_additional_instruction">[설정] -> [권한] -> [위치]에서 권한을 설정해주세요.</string>

<string name="tts_running_start">러닝을 시작합니다!</string>
<string name="tts_running_pause">러닝을 중지합니다!</string>
<string name="tts_running_resume">러닝을 재개합니다!</string>


</resources>

0 comments on commit 3acd13e

Please sign in to comment.