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
51889d6
Update CommandParser.kt
Android-PowerUser Jun 5, 2025
b804b48
I've updated the default model in `GenerativeAiViewModelFactory.kt` f…
google-labs-jules[bot] Jun 5, 2025
c1503f7
Update SystemMessageEntryPreferences.kt
Android-PowerUser Jun 5, 2025
45f8caf
Update SystemMessagePreferences.kt
Android-PowerUser Jun 5, 2025
1a990bd
Update PhotoReasoningScreen.kt
Android-PowerUser Jun 5, 2025
e244948
Update SystemMessageEntryPreferences.kt
Android-PowerUser Jun 5, 2025
5ca64a7
Fix: Correct problematic string in SystemMessageEntryPreferences
google-labs-jules[bot] Jun 5, 2025
0385101
Update SystemMessageEntryPreferences.kt
Android-PowerUser Jun 5, 2025
0a1a643
feat: Implement stop button functionality in PhotoReasoningScreen
google-labs-jules[bot] Jun 5, 2025
6bcffc9
fix: Correct compilation errors in PhotoReasoningViewModel
google-labs-jules[bot] Jun 5, 2025
0480632
fix: Further attempt to correct compilation errors in PhotoReasoningV…
google-labs-jules[bot] Jun 5, 2025
2c37afb
fix: Correct non-local return in sendMessageWithRetry on stop-button …
google-labs-jules[bot] Jun 5, 2025
d7454f7
Here's the plan:
google-labs-jules[bot] Jun 5, 2025
89a9d85
Fix incorrect return statements in PhotoReasoningViewModel
google-labs-jules[bot] Jun 5, 2025
91fd9c0
Delete app/local.properties
Android-PowerUser Jun 5, 2025
c8c4f28
Delete app/src/test/kotlin/com/google/ai/sample directory
Android-PowerUser Jun 5, 2025
3eeea2b
Delete app/src/androidTest/kotlin/com/google/ai/sample/feature/multim…
Android-PowerUser Jun 5, 2025
a744a76
I've fixed some incorrect return statements in `PhotoReasoningViewMod…
google-labs-jules[bot] Jun 5, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ enum class ModelOption(val displayName: String, val modelName: String) {

val GenerativeViewModelFactory = object : ViewModelProvider.Factory {
// Current selected model name
private var currentModelName = ModelOption.GEMINI_FLASH_LITE.modelName
private var currentModelName = ModelOption.GEMINI_FLASH_PREVIEW.modelName

/**
* Set the model to high reasoning capability (gemini-2.5-pro-preview-03-25)
Expand Down Expand Up @@ -95,7 +95,7 @@ val GenerativeViewModelFactory = object : ViewModelProvider.Factory {
// Add companion object with static methods for easier access
object GenerativeAiViewModelFactory {
// Current selected model name - duplicated from GenerativeViewModelFactory
private var currentModelName = ModelOption.GEMINI_FLASH_LITE.modelName
private var currentModelName = ModelOption.GEMINI_FLASH_PREVIEW.modelName

/**
* Set the model to high reasoning capability (gemini-2.5-pro-preview-03-25)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,27 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.Json
import android.util.Log
import kotlinx.serialization.SerializationException

// Define Colors
val DarkYellow1 = Color(0xFFF0A500) // A darker yellow
val DarkYellow2 = Color(0xFFF3C100) // A slightly lighter dark yellow

@Composable
fun StopButton(onClick: () -> Unit) {
Button(
onClick = onClick,
colors = ButtonDefaults.buttonColors(containerColor = Color.Red),
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
) {
Text("Stop", color = Color.White)
}
}

@Composable
internal fun PhotoReasoningRoute(
viewModel: PhotoReasoningViewModel = viewModel(factory = GenerativeViewModelFactory)
Expand Down Expand Up @@ -175,7 +188,8 @@ internal fun PhotoReasoningRoute(
onClearChatHistory = {
mainActivity?.getPhotoReasoningViewModel()?.clearChatHistory(context)
},
isKeyboardOpen = isKeyboardOpen
isKeyboardOpen = isKeyboardOpen,
onStopClicked = { viewModel.onStopClicked() }
)
}

Expand All @@ -191,7 +205,8 @@ fun PhotoReasoningScreen(
isAccessibilityServiceEnabled: Boolean = false,
onEnableAccessibilityService: () -> Unit = {},
onClearChatHistory: () -> Unit = {},
isKeyboardOpen: Boolean
isKeyboardOpen: Boolean,
onStopClicked: () -> Unit = {}
) {
var userQuestion by rememberSaveable { mutableStateOf("") }
val imageUris = rememberSaveable(saver = UriSaver()) { mutableStateListOf() }
Expand Down Expand Up @@ -301,39 +316,45 @@ fun PhotoReasoningScreen(
}
}

Card(modifier = Modifier.fillMaxWidth()) {
Row(modifier = Modifier.padding(top = 16.dp)) {
Column(modifier = Modifier.padding(all = 4.dp).align(Alignment.CenterVertically)) {
IconButton(onClick = { pickMedia.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)) }, modifier = Modifier.padding(bottom = 4.dp)) {
Icon(Icons.Rounded.Add, stringResource(R.string.add_image))
val showStopButton = uiState is PhotoReasoningUiState.Loading || commandExecutionStatus.isNotEmpty()

if (showStopButton) {
StopButton(onClick = onStopClicked)
} else {
Card(modifier = Modifier.fillMaxWidth()) {
Row(modifier = Modifier.padding(top = 16.dp)) {
Column(modifier = Modifier.padding(all = 4.dp).align(Alignment.CenterVertically)) {
IconButton(onClick = { pickMedia.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)) }, modifier = Modifier.padding(bottom = 4.dp)) {
Icon(Icons.Rounded.Add, stringResource(R.string.add_image))
}
IconButton(onClick = onClearChatHistory, modifier = Modifier.padding(top = 4.dp).drawBehind {
drawCircle(color = Color.Black, radius = size.minDimension / 2, style = androidx.compose.ui.graphics.drawscope.Stroke(width = 1.dp.toPx()))
}) { Text("New", style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.primary) }
}
IconButton(onClick = onClearChatHistory, modifier = Modifier.padding(top = 4.dp).drawBehind {
drawCircle(color = Color.Black, radius = size.minDimension / 2, style = androidx.compose.ui.graphics.drawscope.Stroke(width = 1.dp.toPx()))
}) { Text("New", style = MaterialTheme.typography.labelMedium, color = MaterialTheme.colorScheme.primary) }
}
OutlinedTextField(
value = userQuestion,
label = { Text(stringResource(R.string.reason_label)) },
placeholder = { Text(stringResource(R.string.reason_hint)) },
onValueChange = { userQuestion = it },
modifier = Modifier.weight(1f).padding(end = 8.dp)
)
IconButton(onClick = {
if (isAccessibilityServiceEnabled) {
if (userQuestion.isNotBlank()) {
onReasonClicked(userQuestion, imageUris.toList())
userQuestion = ""
OutlinedTextField(
value = userQuestion,
label = { Text(stringResource(R.string.reason_label)) },
placeholder = { Text(stringResource(R.string.reason_hint)) },
onValueChange = { userQuestion = it },
modifier = Modifier.weight(1f).padding(end = 8.dp)
)
IconButton(onClick = {
if (isAccessibilityServiceEnabled) {
if (userQuestion.isNotBlank()) {
onReasonClicked(userQuestion, imageUris.toList())
userQuestion = ""
}
} else {
onEnableAccessibilityService()
Toast.makeText(context, "Enable the Accessibility service for Screen Operator" as CharSequence, Toast.LENGTH_LONG).show()
}
} else {
onEnableAccessibilityService()
Toast.makeText(context, "Enable the Accessibility service for Screen Operator" as CharSequence, Toast.LENGTH_LONG).show()
}, modifier = Modifier.padding(all = 4.dp).align(Alignment.CenterVertically)) {
Icon(Icons.Default.Send, stringResource(R.string.action_go), tint = MaterialTheme.colorScheme.primary)
}
}, modifier = Modifier.padding(all = 4.dp).align(Alignment.CenterVertically)) {
Icon(Icons.Default.Send, stringResource(R.string.action_go), tint = MaterialTheme.colorScheme.primary)
}
}
LazyRow(modifier = Modifier.padding(all = 8.dp)) {
items(imageUris) { uri -> AsyncImage(uri, null, Modifier.padding(4.dp).requiredSize(72.dp)) }
LazyRow(modifier = Modifier.padding(all = 8.dp)) {
items(imageUris) { uri -> AsyncImage(uri, null, Modifier.padding(4.dp).requiredSize(72.dp)) }
}
}
}

Expand Down Expand Up @@ -732,7 +753,7 @@ fun DatabaseListPopup(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.End
) {
Text("Add a new system message guide", color = Color.Black.copy(alpha = 0.6f), style = MaterialTheme.typography.bodyMedium, modifier = Modifier.weight(1f))
Text("This is also sent to the AI", color = Color.Black.copy(alpha = 0.6f), style = MaterialTheme.typography.bodyMedium, modifier = Modifier.weight(1f))
Button(onClick = onNewClicked, colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary), modifier = Modifier.padding(start = 8.dp)) {
Text("New")
}
Expand Down Expand Up @@ -948,7 +969,7 @@ fun ErrorChatBubble(
@Preview
@Composable
fun PhotoReasoningScreenPreviewWithContent() {
MaterialTheme {
MaterialTheme {
PhotoReasoningScreen(
uiState = PhotoReasoningUiState.Success("This is a preview of the photo reasoning screen."),
commandExecutionStatus = "Command executed: Take screenshot",
Expand All @@ -961,7 +982,8 @@ fun PhotoReasoningScreenPreviewWithContent() {
PhotoReasoningMessage(text = "Hello, how can I help you?", participant = PhotoParticipant.USER),
PhotoReasoningMessage(text = "I am here to help you. What do you want to know?", participant = PhotoParticipant.MODEL)
),
isKeyboardOpen = false
isKeyboardOpen = false,
onStopClicked = {}
)
}
}
Expand Down Expand Up @@ -1059,7 +1081,7 @@ val SystemMessageEntrySaver = Saver<SystemMessageEntry?, List<String?>>(
@Composable
@Preview(showSystemUi = true)
fun PhotoReasoningScreenPreviewEmpty() {
MaterialTheme { PhotoReasoningScreen(isKeyboardOpen = false) }
MaterialTheme { PhotoReasoningScreen(isKeyboardOpen = false, onStopClicked = {}) }
}

@Preview(showBackground = true)
Expand Down Expand Up @@ -1088,3 +1110,11 @@ fun DatabaseListPopupEmptyPreview() {
DatabaseListPopup(onDismissRequest = {}, entries = emptyList(), onNewClicked = {}, onEntryClicked = {}, onDeleteClicked = {}, onImportCompleted = {})
}
}

@Preview(showBackground = true, name = "Stop Button Preview")
@Composable
fun StopButtonPreview() {
MaterialTheme {
StopButton {}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,9 @@ sealed interface PhotoReasoningUiState {
data class Error(
val errorMessage: String
): PhotoReasoningUiState

/**
* Operation was stopped by the user
*/
data object Stopped: PhotoReasoningUiState
}
Loading