~ihabunek/toot-discuss

tooi: Status bar improvements v1 APPLIED

Lexi Winter: 1
 Status bar improvements

 4 files changed, 54 insertions(+), 17 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~ihabunek/toot-discuss/patches/48479/mbox | git am -3
Learn more about email & git

[PATCH tooi] Status bar improvements Export this patch

Move the status bar to MainScreen, which is a more appropriate place for
it than TimelineTab.

Add a new ShowStatusMessage message which can be used to display a
status message.

Use ShowStatusMessage to display messages and errors when fetching the
timeline in TimelineTab.
---
 tooi/messages.py           |  5 +++++
 tooi/screens/main.py       | 34 ++++++++++++++++++++++++++++------
 tooi/tabs/timeline.py      | 28 +++++++++++++++++++---------
 tooi/widgets/status_bar.py |  4 ++--
 4 files changed, 54 insertions(+), 17 deletions(-)

diff --git a/tooi/messages.py b/tooi/messages.py
index 2b15fc9..8e2750c 100644
--- a/tooi/messages.py
+++ b/tooi/messages.py
@@ -81,3 +81,8 @@ class ShowStatusMenu(StatusMessage):

class StatusReply(StatusMessage):
    pass

class ShowStatusMessage(Message):
    def __init__(self, text: str | None = None):
        super().__init__()
        self.text = text
diff --git a/tooi/screens/main.py b/tooi/screens/main.py
index 21b4bb1..d7b7202 100644
--- a/tooi/screens/main.py
+++ b/tooi/screens/main.py
@@ -1,13 +1,16 @@
from textual.app import ComposeResult
from textual.binding import Binding
from textual.containers import Vertical
from textual.screen import Screen
from textual.widgets import TabPane, TabbedContent, Footer

from tooi.api.timeline import HomeTimeline, Timeline
from tooi.data.instance import InstanceInfo
from tooi.messages import ShowStatusMessage
from tooi.tabs.search import SearchTab
from tooi.tabs.timeline import TimelineTab
from tooi.widgets.header import Header
from tooi.widgets.status_bar import StatusBar


class MainScreen(Screen[None]):
@@ -32,6 +35,11 @@ class MainScreen(Screen[None]):
    TabPane {
        padding: 0;
    }

    #footer {
        height: 2;
        dock: bottom;
    }
    """

    BINDINGS = [
@@ -51,15 +59,21 @@ class MainScreen(Screen[None]):
    ]

    def __init__(self, instance: InstanceInfo):
        self.instance = instance
        super().__init__()
        self.instance = instance

    def compose(self) -> ComposeResult:
        yield Header("toot")
        # Start with the home timeline
        with TabbedContent():
            yield TimelineTab(self.instance, HomeTimeline(self.instance))
        yield Footer()
        with Vertical():
            yield Header("toot")
            # Start with the home timeline
            with TabbedContent():
                yield TimelineTab(self.instance, HomeTimeline(self.instance))
            with Vertical(id="footer"):
                # Footer() needs to be in its own container, because it forcibly docks itself to the
                # bottom, which would cause it to overlap the status bar.
                with Vertical():
                    yield Footer()
                yield StatusBar()

    async def open_timeline_tab(self, timeline: Timeline, initial_focus: str | None = None):
        tab = TimelineTab(self.instance, timeline, initial_focus=initial_focus)
@@ -67,6 +81,14 @@ class MainScreen(Screen[None]):
        await tc.add_pane(tab)
        tc.active = tab.id

    def on_show_status_message(self, message: ShowStatusMessage):
        status_bar = self.query_one(StatusBar)

        if message.text is None:
            status_bar.clear()
        else:
            status_bar.update(message.text)

    def action_select_tab(self, tabnr: int):
        tc = self.query_one(TabbedContent)
        tabs = tc.query(TabPane)
diff --git a/tooi/tabs/timeline.py b/tooi/tabs/timeline.py
index 5cc56c4..83f090a 100644
--- a/tooi/tabs/timeline.py
+++ b/tooi/tabs/timeline.py
@@ -9,8 +9,7 @@ from tooi.api.timeline import Timeline
from tooi.context import get_context
from tooi.data.instance import InstanceInfo
from tooi.messages import ShowAccount, ShowSource, ShowStatusMenu, ShowThread
from tooi.messages import EventHighlighted, EventSelected, StatusReply
from tooi.widgets.status_bar import StatusBar
from tooi.messages import EventHighlighted, EventSelected, StatusReply, ShowStatusMessage
from tooi.widgets.status_detail import StatusDetail
from tooi.widgets.event_detail import make_event_detail, EventDetailPlaceholder
from tooi.widgets.event_list import EventList
@@ -58,7 +57,6 @@ class TimelineTab(TabPane):
        # Start with an empty status list while we wait to load statuses.
        self.event_list = EventList([])
        self.event_detail = EventDetailPlaceholder()
        self.status_bar = StatusBar()

    def on_show(self, message):
        self.event_list.focus()
@@ -75,7 +73,6 @@ class TimelineTab(TabPane):
            self.event_detail,
            id="main_window"
        )
        yield self.status_bar

    def make_event_detail(self, event: Event):
        return make_event_detail(event)
@@ -88,16 +85,29 @@ class TimelineTab(TabPane):

        newevents = []

        async for eventslist in self.timeline.update():
            newevents += eventslist
        self.post_message(ShowStatusMessage(f"[green]Updating timeline...[/]"))

        try:
            async for eventslist in self.timeline.update():
                newevents += eventslist
        except Exception as exc:
            self.post_message(ShowStatusMessage(f"[red]Could not load timeline: {str(exc)}[/]"))
            return

        # The updates are returned in inverse chronological order, so reverse them before adding.
        newevents.reverse()
        self.event_list.prepend_events(newevents)
        self.post_message(ShowStatusMessage())

    async def fetch_timeline(self):
        self.generator = self.timeline.fetch()
        events = await anext(self.generator)

        try:
            events = await anext(self.generator)
        except Exception as exc:
            self.post_message(ShowStatusMessage(f"[red]Could not load timeline: {str(exc)}[/]"))
            return

        self.event_list.replace(events)
        self.query_one("#main_window").mount(self.event_detail)

@@ -162,14 +172,14 @@ class TimelineTab(TabPane):
    async def maybe_fetch_next_batch(self):
        if self.generator and self.should_fetch():
            self.fetching = True
            self.status_bar.update("[green]Loading statuses...[/]")
            self.post_message(ShowStatusMessage("[green]Loading statuses...[/]"))
            # TODO: handle exceptions
            try:
                next_events = await anext(self.generator)
                self.event_list.append_events(next_events)
            finally:
                self.post_message(ShowStatusMessage())
                self.fetching = False
                self.status_bar.update()

    def should_fetch(self):
        if not self.fetching and self.event_list.index is not None:
diff --git a/tooi/widgets/status_bar.py b/tooi/widgets/status_bar.py
index 511cb8b..90c5483 100644
--- a/tooi/widgets/status_bar.py
+++ b/tooi/widgets/status_bar.py
@@ -1,8 +1,8 @@
from textual.timer import Timer
from textual.widgets import Static
from textual.widgets import Label


class StatusBar(Static):
class StatusBar(Label):
    timer: Timer

    # TODO: support multiple messages
-- 
2.43.0