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
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ class FakeWatchFaceInstallationRepository : WatchFaceInstallationRepository {
_watchFaceInstallationStatus.value = WatchFaceInstallationStatus.NotStarted
}

override suspend fun prepareForTransfer() {
transferId = generateTransferId()
_watchFaceInstallationStatus.value = WatchFaceInstallationStatus.Preparing
}

private fun generateTransferId() = UUID.randomUUID().toString().take(8)

public fun setWatchAsConnected() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,6 @@ class ResultsScreenTest {
val configProvider = ConfigProvider(TestRemoteConfigDataSource(false))
val viewModel = ResultsViewModel(testUri, originalImageUrl = testUri, null, configProvider)


composeTestRule.setContent {
// Disable animation
SharedElementContextPreview {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted.Companion.WhileSubscribed
Expand Down Expand Up @@ -368,10 +369,11 @@ class CustomizeExportViewModel @AssistedInject constructor(

fun installWatchFace() {
val watchFaceToInstall = _state.value.watchFaceSelectionState.selectedWatchFace ?: return
transferJob = viewModelScope.launch {
val bitmap = state.value.exportImageCanvas.imageBitmap
val watch = state.value.connectedWatch
if (watch != null && bitmap != null) {
val bitmap = state.value.exportImageCanvas.imageBitmap
val watch = state.value.connectedWatch
if (watch != null && bitmap != null) {
transferJob = viewModelScope.launch(Dispatchers.Default) {
watchfaceInstallationRepository.prepareForTransfer()
val wfBitmap = imageGenerationRepository.removeBackground(bitmap)
val response = watchfaceInstallationRepository
.createAndTransferWatchFace(watch, watchFaceToInstall, wfBitmap)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ fun getPlaceholderBotUri(): Uri =

@Composable
fun getPlaceholderBotBitmap(): Bitmap =
ImageBitmap.imageResource(id = R.drawable.placeholderbot).asAndroidBitmap()
ImageBitmap.imageResource(id = R.drawable.placeholderbot).asAndroidBitmap()
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ import com.android.developers.androidify.theme.AndroidifyTheme
import com.android.developers.androidify.watchface.WatchFaceAsset

@Composable
fun SendingWatchFacePanel(
fun TransferringWatchFacePanel(
modifier: Modifier = Modifier,
transferLabel: String,
selectedWatchFace: WatchFaceAsset?,
) {
Column(
Expand All @@ -61,8 +62,8 @@ fun SendingWatchFacePanel(
}
Spacer(modifier = Modifier.height(24.dp))
WatchFacePanelButton(
modifier = modifier.padding(horizontal = 16.dp),
buttonText = stringResource(R.string.sending_to_watch),
modifier = Modifier.padding(horizontal = 16.dp),
buttonText = transferLabel,
isSending = true,
colors = ButtonDefaults.buttonColors(
contentColor = MaterialTheme.colorScheme.onSurface,
Expand All @@ -81,8 +82,25 @@ private fun SendingWatchFacePanelPreview() {
previewPath = R.drawable.watch_face_preview,
)
AndroidifyTheme {
SendingWatchFacePanel(
TransferringWatchFacePanel(
selectedWatchFace = watchFace1,
transferLabel = stringResource(R.string.sending_to_watch),
)
}
}

@OptIn(ExperimentalMaterial3Api::class)
@Preview(showBackground = true)
@Composable
private fun PreparingWatchFacePanelPreview() {
val watchFace1 = WatchFaceAsset(
id = "watch_face_1",
previewPath = R.drawable.watch_face_preview,
)
AndroidifyTheme {
TransferringWatchFacePanel(
selectedWatchFace = watchFace1,
transferLabel = stringResource(R.string.preparing_to_send),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ package com.android.developers.androidify.customize.watchface

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.ContentTransform
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
Expand Down Expand Up @@ -108,14 +111,21 @@ fun WatchFaceModalSheet(
AnimatedContent(
targetState = installationStatus,
transitionSpec = {
ContentTransform(
targetContentEnter = fadeIn(
animationSpec = tween(durationMillis = 500),
),
initialContentExit = fadeOut(
animationSpec = tween(durationMillis = 500),
),
)
if (
initialState is WatchFaceInstallationStatus.Preparing &&
targetState is WatchFaceInstallationStatus.Sending
) {
EnterTransition.None togetherWith ExitTransition.None
} else {
ContentTransform(
targetContentEnter = fadeIn(
animationSpec = tween(durationMillis = 500),
),
initialContentExit = fadeOut(
animationSpec = tween(durationMillis = 500),
),
)
}
},
) { installationStatus ->
when (installationStatus) {
Expand Down Expand Up @@ -164,9 +174,17 @@ fun WatchFaceModalSheet(
}
}

is WatchFaceInstallationStatus.Preparing -> {
TransferringWatchFacePanel(
selectedWatchFace = watchFaceSelectionState.selectedWatchFace,
transferLabel = stringResource(R.string.preparing_to_send),
)
}

is WatchFaceInstallationStatus.Sending -> {
SendingWatchFacePanel(
TransferringWatchFacePanel(
selectedWatchFace = watchFaceSelectionState.selectedWatchFace,
transferLabel = stringResource(R.string.sending_to_watch),
)
}

Expand Down
1 change: 1 addition & 0 deletions feature/results/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
<item>Hey good looking!</item>
</string-array>
<string name="send_to_watch">Send to watch</string>
<string name="preparing_to_send">Preparing…</string>
<string name="sending_to_watch">Sending to watch…</string>
<string name="watch_face_sent">Watch face sent</string>
<string name="send_to_watch_device">%s detected.</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class WatchFaceModule {
remoteConfigDataSource: RemoteConfigDataSource,
): WatchFaceInstallationRepository {
val watchFacesEnabled = remoteConfigDataSource.watchfaceFeatureEnabled()
return if (Build.VERSION.SDK_INT >= MIN_WATCH_FACE_SDK_VERSION && watchFacesEnabled) {
return if (Build.VERSION.SDK_INT >= MIN_WATCH_FACE_SDK_VERSION && watchFacesEnabled || true) {
supportedImpl
} else {
noSupportImpl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,6 @@ class EmptyWatchFaceInstallationRepositoryImpl @Inject constructor() : WatchFace
}

override suspend fun resetInstallationStatus() { }

override suspend fun prepareForTransfer() { }
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ interface WatchFaceInstallationRepository {
suspend fun getAvailableWatchFaces(): Result<List<WatchFaceAsset>>

suspend fun resetInstallationStatus()

suspend fun prepareForTransfer()
}

class WatchFaceInstallationRepositoryImpl @Inject constructor(
Expand Down Expand Up @@ -127,4 +129,8 @@ class WatchFaceInstallationRepositoryImpl @Inject constructor(
wearAssetTransmitter.resetTransferId()
manualStatusUpdates.tryEmit(WatchFaceInstallationStatus.NotStarted)
}

override suspend fun prepareForTransfer() {
manualStatusUpdates.tryEmit(WatchFaceInstallationStatus.Preparing)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ sealed class WatchFaceInstallationStatus() {
val validationToken: String,
val activationStrategy: WatchFaceActivationStrategy,
) : WatchFaceInstallationStatus()

object Preparing: WatchFaceInstallationStatus()

object Sending : WatchFaceInstallationStatus()

@Serializable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ fun WatchFaceOnboardingScreen(

when (state) {
is WatchFaceInstallationStatus.Receiving,
is WatchFaceInstallationStatus.Preparing,
is WatchFaceInstallationStatus.Sending,
-> {
TransmissionScreen()
Expand Down