Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify code by removing MessagingTileRenderer #1218

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 @@ -16,10 +16,12 @@
package com.example.wear.tiles.messaging

import android.content.Context
import android.graphics.Bitmap
import androidx.annotation.DrawableRes
import androidx.wear.protolayout.DeviceParametersBuilders
import androidx.wear.protolayout.ModifiersBuilders
import androidx.wear.protolayout.ResourceBuilders
import androidx.wear.protolayout.ResourceBuilders.ImageResource
import androidx.wear.protolayout.ResourceBuilders.Resources
import androidx.wear.protolayout.material.Button
import androidx.wear.protolayout.material.ButtonColors
Expand All @@ -37,9 +39,6 @@ import com.example.wear.tiles.tools.emptyClickable

/**
* Layout definition for the Messaging Tile.
*
* By separating the layout completely, we can pass fake data for the [messagingTilePreview] so it
* can be rendered in Android Studio (use the "Split" or "Design" editor modes).
*/
internal fun messagingTileLayout(
state: MessagingTileState,
Expand Down Expand Up @@ -88,14 +87,14 @@ private fun contactLayout(
}
.build()

private fun Contact.imageResourceId() = "${MessagingTileRenderer.ID_CONTACT_PREFIX}$id"
private fun Contact.imageResourceId() = "${MessagingTileService.ID_CONTACT_PREFIX}$id"

private fun searchLayout(
context: Context,
clickable: ModifiersBuilders.Clickable
) = Button.Builder(context, clickable)
.setContentDescription(context.getString(R.string.tile_messaging_search))
.setIconContent(MessagingTileRenderer.ID_IC_SEARCH)
.setIconContent(MessagingTileService.ID_IC_SEARCH)
.setButtonColors(ButtonColors.secondaryButtonColors(MessagingTileTheme.colors))
.build()

Expand All @@ -113,7 +112,7 @@ private fun messagingTilePreview(context: Context): TilePreviewData {
R.drawable.taylor
)
addIdToImageMapping(
MessagingTileRenderer.ID_IC_SEARCH,
MessagingTileService.ID_IC_SEARCH,
R.drawable.ic_search_24
)
},
Expand Down Expand Up @@ -148,7 +147,7 @@ private fun contactWithImagePreview(context: Context): TilePreviewData {
return TilePreviewData(
onTileResourceRequest = {
Resources.Builder().addIdToImageMapping(
"${MessagingTileRenderer.ID_CONTACT_PREFIX}${contact.id}",
"${MessagingTileService.ID_CONTACT_PREFIX}${contact.id}",
R.drawable.ali
).build()
},
Expand All @@ -163,7 +162,7 @@ private fun contactWithImagePreview(context: Context): TilePreviewData {
private fun searchButtonPreview(context: Context) = TilePreviewData(
onTileResourceRequest = {
Resources.Builder().addIdToImageMapping(
MessagingTileRenderer.ID_IC_SEARCH,
MessagingTileService.ID_IC_SEARCH,
R.drawable.ic_search_24
).build()
},
Expand All @@ -177,11 +176,18 @@ fun Resources.Builder.addIdToImageMapping(
id: String,
@DrawableRes resId: Int
): Resources.Builder = addIdToImageMapping(
id, ResourceBuilders.ImageResource.Builder()
id, ImageResource.Builder()
.setAndroidResourceByResId(
ResourceBuilders.AndroidImageResourceByResId.Builder()
.setResourceId(resId)
.build()
)
.build()
)

fun Resources.Builder.addIdToImageMapping(
id: String,
bitmap: Bitmap
): Resources.Builder = addIdToImageMapping(
id, bitmapToImageResource(bitmap)
)

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ package com.example.wear.tiles.messaging

import android.graphics.Bitmap
import androidx.lifecycle.lifecycleScope
import androidx.wear.protolayout.ResourceBuilders
import androidx.wear.protolayout.ResourceBuilders.Resources
import androidx.wear.protolayout.TimelineBuilders.Timeline
import androidx.wear.tiles.RequestBuilders.ResourcesRequest
import androidx.wear.tiles.RequestBuilders.TileRequest
import androidx.wear.tiles.TileBuilders.Tile
import coil.Coil
import coil.ImageLoader
import com.example.wear.tiles.R
import com.google.android.horologist.tiles.SuspendingTileService
import java.util.UUID
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
Expand All @@ -46,15 +49,13 @@ import kotlinx.coroutines.flow.stateIn
class MessagingTileService : SuspendingTileService() {
private lateinit var repo: MessagingRepo
private lateinit var imageLoader: ImageLoader
private lateinit var renderer: MessagingTileRenderer
private lateinit var tileStateFlow: StateFlow<MessagingTileState?>

override fun onCreate() {
super.onCreate()

repo = MessagingRepo(this)
imageLoader = Coil.imageLoader(this)
renderer = MessagingTileRenderer(this)

tileStateFlow = repo.getFavoriteContacts()
.map { contacts -> MessagingTileState(contacts) }
Expand All @@ -66,12 +67,14 @@ class MessagingTileService : SuspendingTileService() {
}

/**
* Read the latest data, delegating to the [MessagingTileRenderer] which creates a layout to
* which it binds the state.
* Read the latest data, and create a layout to which it binds the state.
*/
override suspend fun tileRequest(requestParams: TileRequest): Tile {
val tileState: MessagingTileState = latestTileState()
return renderer.renderTimeline(tileState, requestParams)
val layoutElement = messagingTileLayout(latestTileState(), this, requestParams.deviceConfiguration)
val resourcesVersion = if (DEBUG_RESOURCES) UUID.randomUUID().toString() else "0"
return Tile.Builder().setResourcesVersion(resourcesVersion).setTileTimeline(
Timeline.fromLayoutElement(layoutElement)
).build()
}

/**
Expand Down Expand Up @@ -102,14 +105,36 @@ class MessagingTileService : SuspendingTileService() {
}

/**
* Downloads bitmaps from the network and passes them to [MessagingTileRenderer] to add as
* image resources (alongside any local resources).
* Downloads bitmaps from the network and adds them to the Resources object
* (alongside any local resources).
*/
override suspend fun resourcesRequest(
requestParams: ResourcesRequest
): ResourceBuilders.Resources {
): Resources {
val avatars = fetchAvatarsFromNetwork(requestParams)
return renderer.produceRequestedResources(avatars, requestParams)
val resourceState = avatars
val resourceIds = requestParams.resourceIds
return Resources.Builder()
.setVersion(requestParams.version)
.apply {
if (resourceIds.isEmpty() || resourceIds.contains(ID_IC_SEARCH)) {
addIdToImageMapping(
ID_IC_SEARCH,
R.drawable.ic_search_24
)
}

// We already checked `resourceIds` in `MessagingTileService` because we needed to know
// which avatars needed to be fetched from the network; `resourceResults` was already
// filtered so it only contains bitmaps for the requested resources.
resourceState.forEach { (contact, bitmap) ->
addIdToImageMapping(
"$ID_CONTACT_PREFIX${contact.id}",
bitmap
)
}
}
.build()
}

/**
Expand All @@ -124,7 +149,7 @@ class MessagingTileService : SuspendingTileService() {
tileState.contacts
} else {
tileState.contacts.filter {
requestParams.resourceIds.contains(MessagingTileRenderer.ID_CONTACT_PREFIX + it.id)
requestParams.resourceIds.contains(MessagingTileService.ID_CONTACT_PREFIX + it.id)
}
}

Expand All @@ -139,4 +164,12 @@ class MessagingTileService : SuspendingTileService() {

return images
}

companion object {
internal const val ID_IC_SEARCH = "ic_search"
internal const val ID_CONTACT_PREFIX = "contact:"
}

}

const val DEBUG_RESOURCES = true