diff --git a/app/src/main/java/com/mshdabiola/playnotepad/ui/NoteApp.kt b/app/src/main/java/com/mshdabiola/playnotepad/ui/NoteApp.kt index c645020a..2f4b8d64 100644 --- a/app/src/main/java/com/mshdabiola/playnotepad/ui/NoteApp.kt +++ b/app/src/main/java/com/mshdabiola/playnotepad/ui/NoteApp.kt @@ -58,6 +58,7 @@ import com.mshdabiola.playnotepad.navigation.NoteNavHost import com.mshdabiola.setting.navigation.navigateToSetting import com.mshdabiola.ui.AudioDialog import com.mshdabiola.ui.ImageDialog2 +import com.mshdabiola.ui.supportVoice import kotlinx.coroutines.launch @OptIn(ExperimentalComposeUiApi::class) @@ -162,9 +163,13 @@ fun NoteApp( appState.coroutineScope.launch { val id = viewModel.insertNewDrawing() appState.navController.navigateToDetail(DetailArg(id.first)) - appState.navController.navigateToDrawing(id.first, id.second) + appState.navController.navigateToDrawing( + id.first, + id.second, + ) } }, + isVoiceSupport = supportVoice(), ) } @@ -246,8 +251,10 @@ fun NoteBottomBar( onAddDrawNote: () -> Unit = {}, onAddVoiceNote: () -> Unit = {}, onAddImageNote: () -> Unit = {}, + isVoiceSupport: Boolean = false, ) { BottomAppBar( + modifier = modifier, actions = { IconButton( modifier = Modifier.testTag("main:check"), @@ -269,14 +276,28 @@ fun NoteBottomBar( ) } - IconButton( - modifier = Modifier.testTag("main:voice"), - onClick = onAddVoiceNote, - ) { - Icon( - imageVector = NoteIcon.KeyboardVoice, - contentDescription = "add note voice", - ) + if (isVoiceSupport) { + IconButton( + modifier = Modifier.testTag("main:voice"), + onClick = onAddVoiceNote, + ) { + Icon( + imageVector = NoteIcon.KeyboardVoice, + contentDescription = "add note voice", + ) + } + } else { + IconButton( + modifier = Modifier.testTag("main:voice"), + onClick = {}, // or show a tooltip + enabled = false, + ) { + Icon( + imageVector = NoteIcon.KeyboardVoice, + contentDescription = "add note voice (unavailable)", + tint = Color.Gray, // or other visual cue + ) + } } IconButton( diff --git a/feature/detail/src/main/kotlin/com/mshdabiola/detail/AddDetailBottomSheet2.kt b/feature/detail/src/main/kotlin/com/mshdabiola/detail/AddDetailBottomSheet2.kt index 0a32ce6a..0261b91c 100644 --- a/feature/detail/src/main/kotlin/com/mshdabiola/detail/AddDetailBottomSheet2.kt +++ b/feature/detail/src/main/kotlin/com/mshdabiola/detail/AddDetailBottomSheet2.kt @@ -36,6 +36,7 @@ fun AddBottomSheet2( onDrawing: () -> Unit = {}, onDismiss: () -> Unit = {}, show: Boolean, + isVoiceSupport: Boolean = false, ) { val background = if (currentImage != -1) { NoteIcon.background[currentImage].fgColor @@ -161,41 +162,43 @@ fun AddBottomSheet2( modifier = androidx.compose.ui.Modifier.testTag("detail:drawing"), ) - NavigationDrawerItem( - icon = { - Icon( - imageVector = NoteIcon.KeyboardVoice, - contentDescription = "", - ) - }, - label = { Text(text = stringResource(Rd.string.modules_designsystem_recording)) }, - selected = false, - onClick = { - onDismiss() - if (context.checkSelfPermission(Manifest.permission.RECORD_AUDIO) == - PackageManager.PERMISSION_GRANTED - ) { - voiceLauncher.launch( - Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply { - putExtra( - RecognizerIntent.EXTRA_LANGUAGE_MODEL, - RecognizerIntent.LANGUAGE_MODEL_FREE_FORM, - ) - putExtra(RecognizerIntent.EXTRA_PROMPT, "Speck Now Now") - putExtra( - "android.speech.extra.GET_AUDIO_FORMAT", - "audio/AMR", - ) - putExtra("android.speech.extra.GET_AUDIO", true) - }, + if (isVoiceSupport) { + NavigationDrawerItem( + icon = { + Icon( + imageVector = NoteIcon.KeyboardVoice, + contentDescription = "", ) - } else { - audioPermission.launch(Manifest.permission.RECORD_AUDIO) - } - }, - colors = NavigationDrawerItemDefaults.colors(unselectedContainerColor = background), - modifier = androidx.compose.ui.Modifier.testTag("detail:recording"), - ) + }, + label = { Text(text = stringResource(Rd.string.modules_designsystem_recording)) }, + selected = false, + onClick = { + onDismiss() + if (context.checkSelfPermission(Manifest.permission.RECORD_AUDIO) == + PackageManager.PERMISSION_GRANTED + ) { + voiceLauncher.launch( + Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply { + putExtra( + RecognizerIntent.EXTRA_LANGUAGE_MODEL, + RecognizerIntent.LANGUAGE_MODEL_FREE_FORM, + ) + putExtra(RecognizerIntent.EXTRA_PROMPT, "Speck Now Now") + putExtra( + "android.speech.extra.GET_AUDIO_FORMAT", + "audio/AMR", + ) + putExtra("android.speech.extra.GET_AUDIO", true) + }, + ) + } else { + audioPermission.launch(Manifest.permission.RECORD_AUDIO) + } + }, + colors = NavigationDrawerItemDefaults.colors(unselectedContainerColor = background), + modifier = androidx.compose.ui.Modifier.testTag("detail:recording"), + ) + } if (!isNoteCheck) { NavigationDrawerItem( icon = { diff --git a/feature/detail/src/main/kotlin/com/mshdabiola/detail/DetailScreen.kt b/feature/detail/src/main/kotlin/com/mshdabiola/detail/DetailScreen.kt index f590d255..38c8d559 100644 --- a/feature/detail/src/main/kotlin/com/mshdabiola/detail/DetailScreen.kt +++ b/feature/detail/src/main/kotlin/com/mshdabiola/detail/DetailScreen.kt @@ -100,6 +100,7 @@ import com.mshdabiola.ui.LabelCard import com.mshdabiola.ui.NotificationDialogNew import com.mshdabiola.ui.ReminderCard import com.mshdabiola.ui.TimeDialog +import com.mshdabiola.ui.supportVoice import com.mshdabiola.ui.toTime import java.io.File import com.mshdabiola.designsystem.R as Rd @@ -219,6 +220,7 @@ internal fun DetailRoute( navigateToDrawing(editViewModel.note.value.id, id) }, onDismiss = { showModalState = false }, + isVoiceSupport = supportVoice(), ) // val images = note.images.map { diff --git a/modules/ui/src/main/kotlin/com/mshdabiola/ui/MainActions.kt b/modules/ui/src/main/kotlin/com/mshdabiola/ui/MainActions.kt index 76540928..474f016a 100644 --- a/modules/ui/src/main/kotlin/com/mshdabiola/ui/MainActions.kt +++ b/modules/ui/src/main/kotlin/com/mshdabiola/ui/MainActions.kt @@ -1,6 +1,7 @@ package com.mshdabiola.ui import android.Manifest +import android.annotation.SuppressLint import android.content.Intent import android.content.pm.PackageManager import android.net.Uri @@ -24,6 +25,7 @@ import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext @@ -101,6 +103,19 @@ fun AudioDialog( ) } +@SuppressLint("QueryPermissionsNeeded") +@Composable +fun supportVoice(): Boolean { + val context = LocalContext.current + + return remember { + val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH) + val pm = context.packageManager + val activities = pm.queryIntentActivities(intent, 0) + activities.isNotEmpty() + } +} + @Composable fun ImageDialog2( modifier: Modifier = Modifier,