Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ android {
applicationId = "com.android.developers.androidify"
minSdk = libs.versions.minSdk.get().toInt()
targetSdk = 36
versionCode = 4
versionName = "1.1.2"
versionCode = 5
versionName = "1.1.3"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,15 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.IntOffset
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator
import androidx.navigation3.runtime.entry
import androidx.navigation3.runtime.entryProvider
import androidx.navigation3.runtime.rememberSavedStateNavEntryDecorator
import androidx.navigation3.ui.NavDisplay
import com.android.developers.androidify.camera.CameraPreviewScreen
import com.android.developers.androidify.creation.CreationScreen
import com.android.developers.androidify.creation.CreationViewModel
import com.android.developers.androidify.customize.CustomizeAndExportScreen
import com.android.developers.androidify.customize.CustomizeExportViewModel
import com.android.developers.androidify.home.AboutScreen
import com.android.developers.androidify.home.HomeScreen
import com.android.developers.androidify.results.ResultsScreen
import com.android.developers.androidify.results.ResultsViewModel
import com.android.developers.androidify.theme.transitions.ColorSplashTransitionScreen
import com.google.android.gms.oss.licenses.OssLicensesMenuActivity

Expand Down Expand Up @@ -98,20 +92,14 @@ fun MainNavigation() {
CameraPreviewScreen(
onImageCaptured = { uri ->
backStack.removeAll { it is Create }
backStack.add(Create(uri))
backStack.add(Create(uri.toString()))
backStack.removeAll { it is Camera }
},
)
}
entry<Create> { createKey ->
val creationViewModel = hiltViewModel<CreationViewModel, CreationViewModel.Factory>(
creationCallback = { factory ->
factory.create(
originalImageUrl = createKey.fileName,
)
},
)
CreationScreen(
createKey.fileName,
onCameraPressed = {
backStack.removeAll { it is Camera }
backStack.add(Camera)
Expand All @@ -122,64 +110,6 @@ fun MainNavigation() {
onAboutPressed = {
backStack.add(About)
},
onImageCreated = { resultImageUri, prompt, originalImageUri ->
backStack.removeAll { it is Result }
backStack.add(
Result(
resultImageUri = resultImageUri,
prompt = prompt,
originalImageUri = originalImageUri,
),
)
},
creationViewModel = creationViewModel,
)
}
entry<Result> { resultKey ->
val resultsViewModel = hiltViewModel<ResultsViewModel, ResultsViewModel.Factory>(
creationCallback = { factory ->
factory.create(
resultImageUrl = resultKey.resultImageUri,
originalImageUrl = resultKey.originalImageUri,
promptText = resultKey.prompt,
)
},
)
ResultsScreen(
onNextPress = { resultImageUri, originalImageUri ->
backStack.add(
CustomizeExport(
resultImageUri = resultImageUri,
originalImageUri = originalImageUri,
),
)
},
onAboutPress = {
backStack.add(About)
},
onBackPress = {
backStack.removeLastOrNull()
},
viewModel = resultsViewModel,
)
}
entry<CustomizeExport> { shareKey ->
val customizeExportViewModel = hiltViewModel<CustomizeExportViewModel, CustomizeExportViewModel.Factory>(
creationCallback = { factory ->
factory.create(
resultImageUrl = shareKey.resultImageUri,
originalImageUrl = shareKey.originalImageUri,
)
},
)
CustomizeAndExportScreen(
onBackPress = {
backStack.removeLastOrNull()
},
onInfoPress = {
backStack.add(About)
},
viewModel = customizeExportViewModel,
)
}
entry<About> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

package com.android.developers.androidify.navigation

import android.net.Uri
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable

Expand All @@ -27,39 +26,10 @@ sealed interface NavigationRoute
data object Home : NavigationRoute

@Serializable
data class Create(
@Serializable(with = UriSerializer::class) val fileName: Uri? = null,
val prompt: String? = null,
) : NavigationRoute
data class Create(val fileName: String? = null, val prompt: String? = null) : NavigationRoute

@Serializable
object Camera : NavigationRoute

@Serializable
object About : NavigationRoute

/**
* Represents the result of an image generation process, used for navigation.
*
* @param resultImageUri The URI of the generated image.
* @param originalImageUri The URI of the original image used as a base for generation, if any.
* @param prompt The text prompt used to generate the image, if any.
*/
@Serializable
data class Result(
@Serializable(with = UriSerializer::class) val resultImageUri: Uri,
@Serializable(with = UriSerializer::class) val originalImageUri: Uri? = null,
val prompt: String? = null,
) : NavigationRoute

/**
* Represents the navigation route to the screen for customizing and exporting a generated image.
*
* @param resultImageUri The URI of the generated image to be customized.
* @param originalImageUri The URI of the original image, passed along for context.
*/
@Serializable
data class CustomizeExport(
@Serializable(with = UriSerializer::class) val resultImageUri: Uri,
@Serializable(with = UriSerializer::class) val originalImageUri: Uri?,
) : NavigationRoute

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,4 @@ class TestFileProvider : LocalFileProvider {
): Uri {
TODO("Not yet implemented")
}

override suspend fun loadBitmapFromUri(uri: Uri): Bitmap? {
return bitmapSample
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package com.android.developers.androidify.util
import android.app.Application
import android.content.ContentValues
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import android.os.Environment
Expand Down Expand Up @@ -54,9 +53,6 @@ interface LocalFileProvider {

@WorkerThread
suspend fun saveUriToSharedStorage(inputUri: Uri, fileName: String, mimeType: String): Uri

@WorkerThread
suspend fun loadBitmapFromUri(uri: Uri): Bitmap?
}

@Singleton
Expand Down Expand Up @@ -124,20 +120,6 @@ class LocalFileProviderImpl @Inject constructor(
return@withContext newUri
}

override suspend fun loadBitmapFromUri(uri: Uri): Bitmap? {
return withContext(ioDispatcher) {
try {
application.contentResolver.openInputStream(uri)?.use {
return@withContext BitmapFactory.decodeStream(it)
}
null
} catch (e: Exception) {
e.printStackTrace()
null
}
}
}

@Throws(IOException::class)
@WorkerThread
private fun saveFileToUri(file: File, uri: Uri) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,18 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.net.toUri
import androidx.graphics.shapes.RoundedPolygon
import androidx.graphics.shapes.rectangle
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import coil3.compose.AsyncImage
import coil3.request.ImageRequest
import coil3.request.crossfade
import com.android.developers.androidify.customize.CustomizeAndExportScreen
import com.android.developers.androidify.customize.CustomizeExportViewModel
import com.android.developers.androidify.data.DropBehaviourFactory
import com.android.developers.androidify.results.ResultsScreen
import com.android.developers.androidify.theme.AndroidifyTheme
import com.android.developers.androidify.theme.LimeGreen
import com.android.developers.androidify.theme.LocalSharedTransitionScope
Expand Down Expand Up @@ -154,41 +159,32 @@ import com.android.developers.androidify.creation.R as CreationR

@Composable
fun CreationScreen(
creationViewModel: CreationViewModel,
fileName: String? = null,
creationViewModel: CreationViewModel = hiltViewModel(),
isMedium: Boolean = isAtLeastMedium(),
onCameraPressed: () -> Unit = {},
onBackPressed: () -> Unit,
onAboutPressed: () -> Unit,
onImageCreated: (resultImageUri: Uri, prompt: String?, originalImageUri: Uri?) -> Unit,
) {
val uiState by creationViewModel.uiState.collectAsStateWithLifecycle()
BackHandler(
enabled = uiState.screenState != ScreenState.EDIT,
) {
creationViewModel.onBackPress()
}
LaunchedEffect(Unit) {
if (fileName != null) {
creationViewModel.onImageSelected(fileName.toUri())
} else {
creationViewModel.onImageSelected(null)
}
}
val pickMedia = rememberLauncherForActivityResult(PickVisualMedia()) { uri ->
if (uri != null) {
creationViewModel.onImageSelected(uri)
}
}
val snackbarHostState by creationViewModel.snackbarHostState.collectAsStateWithLifecycle()

LaunchedEffect(uiState.resultBitmapUri) {
uiState.resultBitmapUri?.let { resultBitmapUri ->
onImageCreated(
resultBitmapUri,
uiState.descriptionText.text.toString(),
if (uiState.selectedPromptOption == PromptType.PHOTO) {
uiState.imageUri
} else {
null
},
)
creationViewModel.onResultDisplayed()
}
}

when (uiState.screenState) {
ScreenState.EDIT -> {
EditScreen(
Expand Down Expand Up @@ -216,6 +212,46 @@ fun CreationScreen(
},
)
}

ScreenState.RESULT -> {
val prompt = uiState.descriptionText.text.toString()
val key = if (uiState.descriptionText.text.isBlank()) {
uiState.imageUri.toString()
} else {
prompt
}
ResultsScreen(
uiState.resultBitmap!!,
if (uiState.selectedPromptOption == PromptType.PHOTO) {
uiState.imageUri
} else {
null
},
promptText = prompt,
viewModel = hiltViewModel(key = key),
onAboutPress = onAboutPressed,
onBackPress = onBackPressed,
onNextPress = creationViewModel::customizeExportClicked,
)
}

ScreenState.CUSTOMIZE -> {
val prompt = uiState.descriptionText.text.toString()
val key = if (uiState.descriptionText.text.isBlank()) {
uiState.imageUri.toString()
} else {
prompt
}
uiState.resultBitmap?.let { bitmap ->
CustomizeAndExportScreen(
resultImage = bitmap,
originalImageUri = uiState.imageUri,
onBackPress = onBackPressed,
onInfoPress = onAboutPressed,
viewModel = hiltViewModel<CustomizeExportViewModel>(key = key),
)
}
}
}
}

Expand Down
Loading