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

Mixing console logging with mosaic #65

Closed
bnorm opened this issue Aug 16, 2022 · 6 comments · Fixed by #66
Closed

Mixing console logging with mosaic #65

bnorm opened this issue Aug 16, 2022 · 6 comments · Fixed by #66

Comments

@bnorm
Copy link
Contributor

bnorm commented Aug 16, 2022

I'd like to create something similar to the rich console output of Gradle with Mosaic, where some kind of table is pinned to the bottom and log messages append above. This is currently doable within Mosaic if I keep a list of these log messages as state and display them first in the content and then the table. But this seems really inefficient as both the log messages and the table are completely cleared from the console and re-written with each update.

What I think I'm looking for is some kind of Appender which is available through MosaicScope that I can call something like println on. The internal AnsiOutput will know how to write those lines after clearing the screen of the previous output but before writing the new output, thus keeping the setContent at the bottom of the console. But this is only what I think and there's probably some better way of doing this.

I'd be happy to mess around with this myself if you like the idea and would be open to contribution.

@JakeWharton
Copy link
Owner

Ink, the library Mosaic is modeled after, calls this Static. I'm definitely down for something which achieves a similar effect. It doesn't need to work exactly like Ink.

@JakeWharton
Copy link
Owner

To your specific implementation suggestion, we can kinda make the implementation work like that but you would be forced to wrap everything in a SideEffect for it to technically be correct. We don't want to log unless the recomposition is applied and not canceled. So while Static is somewhat weird, it basically hides this fact as part of the tree. So once a tree is complete and we go to emit, we clear the previous lines, traverse the tree for all statics and log them, and then do another traversal to emit the normal output.

@JakeWharton
Copy link
Owner

If you want to give that way a shot feel free. Otherwise I'll get to it after Droidcon NYC.

@bnorm
Copy link
Contributor Author

bnorm commented Aug 17, 2022

This is great info and a really clear direction to head. I'll give it a shot and see how far I can get.

@bnorm
Copy link
Contributor Author

bnorm commented Aug 18, 2022

Just leaving myself some notes.

So I think I've got a design that I like for extracting the static parts of the tree into something that's displayable. I'll put up a draft PR soon to make sure I'm heading in a good direction there. However, I'm struggling with how we can make those parts of the tree only render a single time. I'm hoping there are things within the Compose runtime which can help, but this is probably where my lack of in-depth knowledge of Compose hurts.

Ink uses useLayoutEffect to update the index of the last item displayed. If we want to follow a similar pattern, I think a Flow might be a better input with an internal list of items which haven't been displayed. Maybe we can use SideEffect to clear the items? Or just clear the items immediately after looping over them? Still experimenting but any suggestions are welcome.

@JakeWharton
Copy link
Owner

Yeah it's an interesting implementation. It seems like they basically force you keep all your previous static output as if it were rendering each time but then they only render after the index pointer.

The big advantage of doing it that way is that you can still use all the cool rendering mechanisms on that static content. The downside is that you have to maintain the state to pretend to rerender everything static.

If you exposed something based on a side effect that just offered a way to write strings you lose the ability to do fancy rendering, but it means you could fire and then forget your logs.

I'm not sure what the right path forward is here. We should try to build a fake Gradle sample or something to get a feel for it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants