Module userland.scripts.messages.filter_modal

Filter messages screen

Classes

class FilterModal (*args, tags: list[str] | None = None, **kwargs)

Filter messages screen

Initialize the screen.

Args

name
The name of the screen.
id
The ID of the screen in the DOM.
classes
The CSS classes for the screen.
Expand source code
class FilterModal(ModalScreen[list[str]]):
    """Filter messages screen"""

    CSS = """
        FilterModal {
            align: center middle;
            background: rgba(0, 0, 0, 0.5);
        }

        Button {
            margin: 1;
            width: 50%;
        }

        Label {
            margin-top: 1;
        }

        Input {
            width: 54;
        }

        #autocomplete_wrapper {
            height: 5;
        }

        #filter {
            margin-left: 0;
            margin-top: 1;
        }

        #wrapper {
            background: $primary-background;
            height: 15;
            padding: 1;
            width: 60;
        }
    """

    _tags: list[str]
    _alltags: list[str] = []

    def __init__(self, *args, tags: list[str] | None = None, **kwargs):
        super().__init__(*args, **kwargs)
        self._tags = tags or []

    def compose(self):
        yield Vertical(
            Horizontal(
                Label("Tags"),
                Input(" ".join(self._tags)),
            ),
            Horizontal(OptionList(disabled=True), id="autocomplete_wrapper"),
            Horizontal(
                Button("Filter", variant="success", id="filter", name="filter"),
                Button("Cancel", variant="error", id="cancel", name="cancel"),
            ),
            id="wrapper",
        )

    def _submit(self) -> None:
        tags = self.query_one(Input)
        assert tags
        self.dismiss(tags.value.split(" "))

    async def on_mount(self) -> None:
        self._alltags = [t.name for t in await MessageTag.query.gino.all()]

    def on_button_pressed(self, event: Button.Pressed) -> None:
        if event.button.name == "cancel":
            self.app.pop_screen()  # pop this modal
            return

        self._submit()

    async def on_input_changed(self, event: Input.Changed) -> None:
        last_word = event.input.value.split(" ")[-1]
        selections = self.query_one(OptionList)
        selections.clear_options()

        if last_word == "":
            selections.disabled = True
            return

        suggestions = [
            Option(t) for t in self._alltags if t.startswith(last_word)
        ]
        selections.disabled = False
        selections.add_options(suggestions)

    async def on_input_submitted(self, event: Input.Submitted) -> None:
        self._submit()

    async def on_option_list_option_selected(
        self, event: OptionList.OptionSelected
    ) -> None:
        tags_input = self.query_one(Input)
        tags = tags_input.value.split(" ")[:-1]
        tags.append(str(event.option.prompt))
        tags_input.value = "".join([" ".join(tags), " "])
        tags_input.focus()
        event.option_list.clear_options()
        event.option_list.disabled = True

    async def key_escape(self, _):
        self.app.pop_screen()  # pop this modal

Ancestors

  • textual.screen.ModalScreen
  • textual.screen.Screen
  • typing.Generic
  • textual.widget.Widget
  • textual.dom.DOMNode
  • textual.message_pump.MessagePump

Class variables

var CSS
var can_focus
var can_focus_children

Methods

def compose(self)

Called by Textual to create child widgets.

This method is called when a widget is mounted or by setting recompose=True when calling [refresh()][textual.widget.Widget.refresh].

Note that you don't typically need to explicitly call this method.

Example

def compose(self) -> ComposeResult:
    yield Header()
    yield Label("Press the button below:")
    yield Button()
    yield Footer()
async def key_escape(self, _)
def on_button_pressed(self, event: textual.widgets._button.Button.Pressed) ‑> None
async def on_input_changed(self, event: textual.widgets._input.Input.Changed) ‑> None
async def on_input_submitted(self, event: textual.widgets._input.Input.Submitted) ‑> None
async def on_mount(self) ‑> None
async def on_option_list_option_selected(self, event: textual.widgets._option_list.OptionList.OptionSelected) ‑> None