Starting to look a little into Tiles and proto stu...
# compose-wear
t
Starting to look a little into Tiles and proto stuff. I wanted to quickly iterate on the proto-material to build my M3 version for a simple media tile, but it seems many things are restricted API in LayoutElementBuilders, is there a reason except API surface maintenance and I can ignore until an M3 version is built?
y
I probably can't answer for that team, but can you give some examples you need.
t
Well as a starter I just want to iterate small changes to the golden media tile with the last 2 played collections and a quick access button. Since there's already all and it's just design details I hoped I could just copy paste. I can easily silence the restrictions so will probably still go that road, no need to rewrite all from scratch.
y
Can you grab a screenshot to demonstrate which methods are flagged? There are a lot of methods not part of public API, for example all the low level proto methods.
t
It's the
LayoutElement
interface members. So it prevent extending
LayoutElementBuilders.LayoutElement.Builder
and
toLayoutElementProto
/
getFingerprint
but that's the base of the layout constructions in proto material.
y
cc @Mohammad Saboorian
It's not designed for the way you are trying to use it, I think you'll have pain doing it this way.
t
As often with all the material stuff everything is private / internal making it quite hard to adapt a few details without getting into deep mess. To fix bottomsheet in normal M3 it's 5 files to copy. I guess I'll use the default layouts for now and see how it goes.
y
As an example I don't think the Proto are public API, I think androidx doesn't allow that. At least in Android Studio I get this
image.png
I'd suggest a Feature Request explaining what you need to do, and seeing if they can cleanly support it.
t
It's just one more implementation to add to fix.
βž• 1
The need is to tweak Material stuff but I already know the answer as I tried for normal M3. I do not understand yet enough the proto stuff to know how to build a proper design system as the Material one from scratch to be able to make a feature requests.
But I would have assumed the base stuff would have been reusable as a starter.
I know you can suppress the errors and continue, but just be aware it may break in future. As long as you are aware of that risk, I'm sure you can do what you want. It may be a stretch to call it material3 as I don't think the UX designs are final, and the code obviously isn't.
t
Yes I've seen, but even then I often do small tweaks on M3 to better fit my users needs or fix bugs.
πŸ‘πŸ» 1
I just want consistency with the wear app that will have M3 components as Material ones are ugly by default πŸ˜› And consistency with the phone app that fully embrace M3 with tons of users configuration.
y
Nice. I've done the same with contributions to Confetti, syncing Mobile Material 3 Theme Color to Wear Material.
I know it's a pain, but I'd encourage you to raise bugs or feature requests, they do get seen and hopefully fixed, and they do affect the roadmap.
t
I opened many many many many issues and FR since 12 years on Google tracker now πŸ˜‰ But for M3 on wear it's too early they probably don't even know what they'll do yet.
BTW from the docs tiles are supposed to show the app icon at the top for a moment and I don't get them on emulator is there something special to do ?
arf it linked an image not the animation 😞
and also not on the pixel watch 2.
y
I think it's more that the Manufacturer (Pixel, Samsung, OnePlus, etc) is free to show it there, so you should avoid putting your own icon or content there.
t
Ok so I really need to have the theme and colors match the app for easy understanding by the user, thanks.
πŸ‘πŸ» 1
y
Yeah, and particularly a clear empty state screen if user has installed, but not logged in. With content, maybe it's obvious. Less so before then.
t
And last question, is there a way to get the timestamp / date of the last timeline in the service oncreate to know if I should push an update? I suppose requesting update everytime the data change even if the user have not added the tile is not efficient.
y
I think store that yourself, and use the methods that track whether the tile is installed (getActiveTilesAsync).
But the counter argument is that requestUpdate doesn't force an update. All it does it mark the tile dirty, and the system will refresh when appropriate.
Some combination of time and whether your tile is open, or +- 1 on the carousel.
So maybe it's cheap enough to call, but it would suggest limiting how much time you should spend generating a timeline.
t
It's cheap it's showing the last 2 most recently played collections, I'll test the simple way for now then thanks again.
πŸ‘πŸ» 1
Now just need to find how to link the Clickables and wear navigation compose.
y
LaunchAction isn't really friendly for wear navigation compose, so I'd encourage another approach.
trying to dig it out.
t
Like intercepting the onNewIntent and manually navigate ?
That's what I usually do for some exotic navigation patterns.
y
Copy code
override suspend fun tileRequest(requestParams: RequestBuilders.TileRequest): TileBuilders.Tile {
        val lastClickableId = requestParams.currentState.lastClickableId
        if (lastClickableId.isNotBlank()) {
            handleClick("<confetti://confetti/$lastClickableId>")
        }

        return renderer.renderTimeline(tileState(), requestParams)
    }

    private fun handleClick(uri: String) {
        TaskStackBuilder.create(this)
            .addNextIntentWithParentStack(
                Intent(
                    Intent.ACTION_VIEW,
                    uri.toUri()
                )
            )
            .startActivities()
    }
You are meant to have a synthetic backstack, and I don't think LaunchAction supports it cleanly, it wasn't built for the single activity architecture I feel.
t
Ok thanks, that seems easy to even if that mean linking modules together to handle debug / prod schemes.
y
Whatever works for you. If I try to follow our MAD guidance for navigation, this is the approach I use.
t
I'm a big fan of dynamic navigation and modules registration and agnostic routes and things that are harder with compose navigation hence why I preferred Voyager in the main app (not talking about passing actual items, because when you navigate with remote not locally cached data you can't just pass an id, but this is now being addressed). I just need to read more and adapt.
πŸ‘πŸ» 1
Sorry to bother you again, but you are incredibly valuable and makes me go ultra fast today πŸ™‚ I'm reusing the NavigationScreens concept from Horologist and just added the lastClickableId and it work nicely with the deeplink, but how can I add some screens in the backstack with that design?
πŸ‘€ 1
y
Great question - that code above is meant to do that.
addNextIntentWithParentStack
should understand your navigation structure. But worth confirming.
But it does assume you have deeplinks set up.
t
Hum I probably missed something then will do the reading. I just declare the routes in the Composable calls and it works by magic, maybe too much magic is not good :)
y
Something like
Copy code
composable<Prompt>(
                deepLinks = listOf(navDeepLink {
                    uriPattern = "<myApp://myapp/prompt>"
                })
            ) {
                SamplePromptScreen(
                    onSettingsClick = { navController.navigate(Settings) },
                )
            }
And in your manifest
Copy code
<intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data
                    android:host="myapp"
                    android:scheme="myapp" />
            </intent-filter>
t
Yes this works that part I get right. But for the title I go directly to a sub sub screen, currently it open the right screen but when going back it goes to root of app and does not have the intermediary backstack entries.
If there's nothing special to horologist Navigation screens I'll do the reading, probably something obvious.
☝🏻 1
y
I think you are right, seems awkward in Compose Navigation. Might require a nested navigation graph https://developer.android.com/guide/navigation/principles#deep-link links to https://developer.android.com/guide/navigation/design/nested-graphs which has a typesafe compose sample
t
Thanks I will read that.
Since the intermediary level requires a parameter that can be dynamic it seems from all the posts I can see there's no solution. I suppose this does not matter that much as from the tile they probably will want to play and return to home anyway.
πŸ‘πŸ» 1
One last I promise (for today :p) I've opened https://github.com/google/horologist/issues/2253
Ok so I lied 😞 I'm struggling to find documentation about the proper way to handle resource versioning and image fallback. I can build a version scheme related to the elements shown in the state, but the resources ids are generated before they are loaded. So if the image download fail and I return a default image, that will be cached and Wear won't ask for the ressource again later to try to download the image. Is there a proper way to handle this?
y
AFAIK resource versions are essentially immutable.
β€’ newly added ids in a subsequent tile fetch, won't get requested β€’ Placeholders for errors won't get corrected
My advice β€’ Use Coil with Caching - ensure it's as likely as possible you have fetched and cached images you are likely to put on screen ahead of time.
β€’ You can fetch the images in the the tileRequest and compute some sort of hash for the results including errors, so you'll keep generating new resource version when either content or failed images change.
t
I'm already using coil and caching and specific fetchers via wear channels and everything. And I like the SuspendingTileService and SingleTileLayoutRenderer helped me gain time. In the end took me a couple of hours to build a fully working tile except this small detail (and design not fully to my liking yet). I'll add the last played used for the sort to the ressource version, this will ensure a reload each time they play something at least that should be enough. Thanks again for all the help, that part is not the best documented about wear.
βž• 1
y
I messed up versions for a long while
Also nothing ever passes in the resource IDs. So you have to link yourself to the tile request
t
Yes the codelab code shown some stuff I reused. There's many different parts and samples everywhere but once all the small parts are found, it kinda works πŸ™‚
Now the hard part will be to try to change the chip design to match the wear app, I hope I can still copy paste a few stuff from the proto-material and don't need to rewrite all by hand.
Anyway thanks again you were invaluable today πŸ™‚
πŸ‘ 1
y
Closing a bug before it's 2nd birthday https://github.com/google/horologist/pull/2255
t
Was not really a bug πŸ™‚ (Not working on that app to test today, but you might want to test the 565 to 8888 upscale that is now allowed, IIRC I had some real ugly banding on some case when doing that but that was a long time ago since I played with those cases)
y
That was why i set it to false in coil api
If you have a good test case feel free to add
But I don't have a solution to fix that, maybe apps need to plan for it?
t
Yes but that function is not tied to coil, anyone can use it with any kind of bitmaps. I my case the images are direct from cache if already cached.
Or add a warning in the doc maybe? Not sure what is the best course here.
Actually doc was not updated.
Maybe keep the current API without a parameter that can only downscale, and a new version with the param and no default to force read the doc? and the previous default calling the new one ?
y
Care to comment on the PR. I'm having hard time following slack
t
Yeah sorry not on the right computer right now, will follow up tommorow there.
πŸ‘ 1
m
Sorry for missing the ping. As Yuri mentioned, those types are not meant to be extended the way you want. I understand the frustration with the current protolayout-material library not allowing much customization. This is an important feedback that we’re keeping in mind when building protolayout-material3. Any additional feedback is welcome too.
t
The feedback is mostly that material design is fixed and not always meant to be configurable, even if there's changes with the new expressive stuff. And that's fine, but having the base blocks used being less internal/ private to allow copy paste and modifications would be nice. Because not being able to copy paste and not even being able to reuse the concepts to rebuild something leaves us a little alone on how to achieve a different design.
πŸ‘ 1
βž• 1