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

Add Kino.Controls for user interactions #50

Merged
merged 17 commits into from
Dec 2, 2021
Merged

Add Kino.Controls for user interactions #50

merged 17 commits into from
Dec 2, 2021

Conversation

jonatanklosko
Copy link
Member

For the Livebook counterpart see livebook-dev/livebook#710.

Introduces UI controls that allow the user to feed events into any process that subscribes. I built a multiplayer Pong as a driving showcase, but we already have some cooler things in mind 😸

Basic usage

pong_events.mp4

Notebook preview

pong_notebook.mp4

The game

pong.mp4

@jonatanklosko
Copy link
Member Author

Here is the current notebook. I think that's something we could have in the Explore section.

@josevalim
Copy link
Contributor

This is absolutely amazing!

My only comment for now is, instead of having a control with different kinds of inputs, we should have different controls and find a mechanism for rendering multiple elements in the same frame. Perhaps it could be as simple as allowing a list in frame? Some elements could be inline-block by default and others block, which means they also get nicely formatted.

@jonatanklosko
Copy link
Member Author

I split it into individual controls and implemented subscription for controls and inputs. There is still a number of things, like anonymous functions and un-sync, but I've just pushed the changes, so let me know what you think of the API.

In particular I made it so that the event name is specified when subscribing, like Kino.Control.subscribe(button, :hello), while previously it would be a part of the button. The primary reason is that otherwise we would need to pass event name when creating inputs for consistency, which feels backwards and in many cases unnecessary.

controls_inputs.mp4

lib/kino/control.ex Outdated Show resolved Hide resolved
lib/kino/control.ex Outdated Show resolved Hide resolved
lib/kino.ex Outdated Show resolved Hide resolved
lib/kino/control.ex Outdated Show resolved Hide resolved
@jonatanklosko
Copy link
Member Author

I've updated the Pong notebook to match the new design.

def start_child(child_spec) do
# Starting a process that calls Kino.start_child/1 in its init
# would block forever, so we don't allow nesting
if Kino.DynamicSupervisor in Process.get(:"$ancestors", []) do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add a test for this to make sure it is triggered. Something like this should trigger it:

Kino.start_child({Task, fn -> Kino.start_child({Task, fn -> :ok end}) end})

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call! We need the assertion in the inner call, so I made the test wait for the outer process to terminate, let me know if there's any better way :)

lib/kino.ex Outdated Show resolved Hide resolved
lib/kino.ex Outdated Show resolved Hide resolved
lib/kino.ex Outdated Show resolved Hide resolved
Copy link
Contributor

@josevalim josevalim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just dropped one comment, plus the changes we discussed in Slack, then we are good to go!

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 this pull request may close these issues.

2 participants