Spent some time this weekend hacking on my text fo...
# compose
z
Spent some time this weekend hacking on my text formatting experiment project and finally implemented support for links and stuff. My general goal here is to get a feel for what a sort of Compose-based markup DSL for creating fancy text (roughly on the same level of flexibility as Markdown) could be like, while keeping formatting details consistent and centralized. It’s super rough, and there are some gross hacks here, and no tests, but the API turned out kinda nice. https://github.com/zach-klippenstein/compose-richtext/pull/3
👍 18
t
this is really cool!
l
this is really great. were there any particular pain points you’d like to call out? I will also look through the code
it would be cool to see someone build a markdown to annotated string converter
z
☝️ that was actually my original goal, and then I realized there were a lot of markdown concepts that aren't expressible with Span/Paragraph styles and that extracting out this layer would also make it easy to build renderers for other markdown/markup formats.
It's been a really good way to explore writing custom layouts. I initially used the Table composable for both lists and tables, but when that disappeared I realized most of the behavior was just easier to achieve with custom layouts, and more easily customizable too.
I did find some issues, and I would have written them up but I ran out of time last night lol. One thing from this weekend was some awkwardness with the InlineTextContent API. I haven't made a reproducer yet but passing in a new map doesn't always trigger a relayout of the text. You'll see a bunch of comments where I append zero-width characters to the string to force relayout when the placeholders' sizes change. The reason I ran into that was due to trying to hide the placeholder API altogether. The cheat I'm using now is to use the first composition to measure the inline contents using the Text's layout constraints, then immediately recalculating new Placeholders with the results. This isn't ideal, since there's a frame where they content is all zero-sized and you see it jump into place (it's even visible in that gif). I don't know if that's avoidable though since the content would need to finish measurement + layout before starting text layout, and text layout is required to measure the text node, so there's a circular dependency. Something that does seem fixable though is that Density throws an exception if you try to convert an em TextUnit to pixels. This makes sense in most cases, since ems are relative to font metrics and don't have any meaning outside of a specific font. But when inline content is composed, it is in the context of a specific font. It seems like it should be possible for Compose to merge all the SpanStyles and TextStyles, determine the font, load the font metrics, and pass a special Density ambient to inline composables that had support for em conversions. That said, this is only really an issue if they need to measure things in ems, which is really only necessary if you're trying to calculate the Placeholder lazily as described above.
I found at least one crash too, I think a race condition that I triggered once by clicking on that link in the gif right when the resizing inline content started changing, but I haven't been able to repro.
Definitely the weirdest bug of the weekend was that the property initializer for a property in the companion object defined at the bottom of a sealed class with nested subclasses was seeing the first
object
"case class" in the sealed class as null. Doesn't seem like anything to do with compose, but I've never seen that before.
l
sounds like at least one bug (probably more) and a few concrete pieces of API feedback
the inline text content API hasn’t gone through API review yet so there will likely be some changes there
z
Ah, I see. It’s definitely useful to be able to embed composables, it kind of blew my mind a little when I dropped a classic Android
Button
in one of them too and it Just Worked. I’m really curious how they’re going to play with accessibility, e.g. I’m not sure how to make links show up correctly to screen readers with actions and focus and descriptions and stuff. I figure it’s probably possible by manually passing a bunch of coordinates and lambdas to a
semantics
modifier somehow and manually drawing indicators, but I know that stuff is being actively worked on so i’ll just sit back and 🍿