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

A message posted from a modal callback doesn't bubble to app #3291

Closed
davep opened this issue Sep 13, 2023 · 1 comment · Fixed by #3315
Closed

A message posted from a modal callback doesn't bubble to app #3291

davep opened this issue Sep 13, 2023 · 1 comment · Fixed by #3315
Assignees
Labels

Comments

@davep
Copy link
Contributor

davep commented Sep 13, 2023

This might be a symptom of something more general, but I'm recording it here for further investigation or clarification after the question was asked on Discord.

Short version: if, from within a widget, a message is posted from a callback initiated from the dismissal of a modal screen, the message seems to stop bubbling at the screen. On the other hand a message posted "directly" on the widget bubbles up to the application.

To illustrate, the following app can help show it off:

from dataclasses import dataclass

from textual import on
from textual.app import App, ComposeResult
from textual.containers import Horizontal, Vertical
from textual.message import Message
from textual.screen import ModalScreen
from textual.widgets import Button, Log


class TestModal(ModalScreen[str]):

    DEFAULT_CSS = """
    TestModal {
        align: center middle
    }
    """

    def compose(self) -> ComposeResult:
        yield Button("Close and send message")

    @on(Button.Pressed)
    def close_and_send(self) -> None:
        self.dismiss("From the modal screen")


class TestWidget(Vertical):

    DEFAULT_CSS = """
    TestWidget Horizontal {
        align: center middle;
        height: auto;
    }

    TestWidget Horizontal > Button {
        margin: 0 4 0 4;
    }

    TestWidget Log {
        border: solid green;
    }
    """

    @dataclass
    class TestMessage(Message):
        came_from: str

    def compose(self) -> ComposeResult:
        with Horizontal():
            yield Button("Just send the message", id="send_now")
            yield Button("Open a modal screen", id="send_via_modal")
        yield Log()

    @on(Button.Pressed, "#send_now")
    def message_from_here(self) -> None:
        self.post_message(self.TestMessage("Directly from a post_message"))

    def modal_callback(self, calling_from: str) -> None:
        self.post_message(self.TestMessage(calling_from))

    @on(Button.Pressed, "#send_via_modal")
    def message_from_callback(self) -> None:
        self.app.push_screen(TestModal(), callback=self.modal_callback)

class CallbackBubbleIssueApp(App[None]):

    def compose(self) -> ComposeResult:
        yield TestWidget()

    @on(TestWidget.TestMessage)
    def log_message(self, event: TestWidget.TestMessage) -> None:
        self.query_one(Log).write_line(f"{event!r}")


if __name__ == "__main__":
    CallbackBubbleIssueApp().run()

When run, press the Just send the message button and the message will appear in the log. On the other hand, if you press the From the modal screen button and then press the button on the resulting modal screen, no message gets logged.

This can also be seen in the textual console, where the in the latter case the only even logs are these:

TestWidget.TestMessage(came_from='From the modal screen') >>> TestWidget() method=None
TestWidget.TestMessage(came_from='From the modal screen') >>> Screen(id='_default') method=None

whereas when sent "directly":

TestWidget.TestMessage(came_from='Directly from a post_message') >>> TestWidget() method=None
TestWidget.TestMessage(came_from='Directly from a post_message') >>> Screen(id='_default') method=None
TestWidget.TestMessage(came_from='Directly from a post_message') >>> CallbackBubbleIssueApp(title='CallbackBubbleIssueApp', classes={'-dark-mode'}) method=<CallbackBubbleIssueApp.on_test_widget_test_message>

This feels like a bug, but I don't want to label it as such until it's clearer what's going on here. Even the subject for the issue is up in the air as this could just be a very specific instance of a more general thing.

@davep davep added the Task label Sep 13, 2023
davep added a commit to davep/textual-sandbox that referenced this issue Sep 13, 2023
@willmcgugan willmcgugan self-assigned this Sep 15, 2023
@github-actions
Copy link

Don't forget to star the repository!

Follow @textualizeio for Textual updates.

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

Successfully merging a pull request may close this issue.

2 participants