mirror of
https://github.com/ihabunek/toot.git
synced 2025-01-03 14:56:37 -05:00
Add basic timeline switching
This commit is contained in:
parent
07e6c372bc
commit
350138324b
@ -30,7 +30,9 @@ TODO/Ideas:
|
||||
* reblog
|
||||
* show author in status list, not person who reblogged
|
||||
* "v" should open the reblogged status, status.url is empty for the reblog
|
||||
|
||||
* overlays
|
||||
* stack overlays instead of having one?
|
||||
* current bug: press U G Q Q - second Q closes the app instead of closing the overlay
|
||||
|
||||
Questions:
|
||||
* is it possible to make a span a urwid.Text selectable? e.g. for urls and hashtags
|
||||
|
@ -12,6 +12,7 @@ from .constants import PALETTE
|
||||
from .entities import Status
|
||||
from .timeline import Timeline
|
||||
from .utils import show_media
|
||||
from .widgets import Button
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -90,7 +91,6 @@ class TUI(urwid.Frame):
|
||||
self.loop = None # set in `create`
|
||||
self.executor = ThreadPoolExecutor(max_workers=1)
|
||||
self.timeline_generator = api.home_timeline_generator(app, user, limit=40)
|
||||
# self.timeline_generator = api.public_timeline_generator(app.instance, local=False, limit=40)
|
||||
|
||||
# Show intro screen while toots are being loaded
|
||||
self.body = self.build_intro()
|
||||
@ -105,7 +105,8 @@ class TUI(urwid.Frame):
|
||||
super().__init__(self.body, header=self.header, footer=self.footer)
|
||||
|
||||
def run(self):
|
||||
self.loop.set_alarm_in(0, lambda *args: self.async_load_statuses(is_initial=True))
|
||||
self.loop.set_alarm_in(0, lambda *args:
|
||||
self.async_load_timeline(is_initial=True, timeline_name="home"))
|
||||
self.loop.run()
|
||||
self.executor.shutdown(wait=False)
|
||||
|
||||
@ -160,6 +161,7 @@ class TUI(urwid.Frame):
|
||||
|
||||
future = self.executor.submit(fn, *args, **kwargs)
|
||||
future.add_done_callback(_done)
|
||||
return future
|
||||
|
||||
def connect_default_timeline_signals(self, timeline):
|
||||
def _compose(*args):
|
||||
@ -187,17 +189,17 @@ class TUI(urwid.Frame):
|
||||
urwid.connect_signal(timeline, "media", _media)
|
||||
urwid.connect_signal(timeline, "menu", _menu)
|
||||
|
||||
def build_timeline(self, statuses):
|
||||
def build_timeline(self, name, statuses):
|
||||
def _close(*args):
|
||||
raise urwid.ExitMainLoop()
|
||||
|
||||
def _next(*args):
|
||||
self.async_load_statuses(is_initial=False)
|
||||
self.async_load_timeline(is_initial=False)
|
||||
|
||||
def _thread(timeline, status):
|
||||
self.show_thread(status)
|
||||
|
||||
timeline = Timeline("home", statuses)
|
||||
timeline = Timeline(name, statuses)
|
||||
|
||||
self.connect_default_timeline_signals(timeline)
|
||||
urwid.connect_signal(timeline, "next", _next)
|
||||
@ -229,7 +231,7 @@ class TUI(urwid.Frame):
|
||||
self.body = timeline
|
||||
self.refresh_footer(timeline)
|
||||
|
||||
def async_load_statuses(self, is_initial):
|
||||
def async_load_timeline(self, is_initial, timeline_name=None):
|
||||
"""Asynchronously load a list of statuses."""
|
||||
|
||||
def _load_statuses():
|
||||
@ -245,7 +247,7 @@ class TUI(urwid.Frame):
|
||||
|
||||
def _done_initial(statuses):
|
||||
"""Process initial batch of statuses, construct a Timeline."""
|
||||
self.timeline = self.build_timeline(statuses)
|
||||
self.timeline = self.build_timeline(timeline_name, statuses)
|
||||
self.timeline.refresh_status_details() # Draw first status
|
||||
self.refresh_footer(self.timeline)
|
||||
self.body = self.timeline
|
||||
@ -255,7 +257,7 @@ class TUI(urwid.Frame):
|
||||
existing timeline."""
|
||||
self.timeline.append_statuses(statuses)
|
||||
|
||||
self.run_in_thread(_load_statuses,
|
||||
return self.run_in_thread(_load_statuses,
|
||||
done_callback=_done_initial if is_initial else _done_next)
|
||||
|
||||
def refresh_footer(self, timeline):
|
||||
@ -290,6 +292,32 @@ class TUI(urwid.Frame):
|
||||
urwid.connect_signal(composer, "post", _post)
|
||||
self.open_overlay(composer, title="Compose status")
|
||||
|
||||
def show_goto_menu(self):
|
||||
menu = GotoMenu()
|
||||
urwid.connect_signal(menu, "home_timeline",
|
||||
lambda x: self.goto_home_timeline())
|
||||
urwid.connect_signal(menu, "local_public_timeline",
|
||||
lambda x: self.goto_public_timeline(True))
|
||||
urwid.connect_signal(menu, "global_public_timeline",
|
||||
lambda x: self.goto_public_timeline(False))
|
||||
|
||||
self.open_overlay(menu, title="Go to", options=dict(
|
||||
align="center", width=("relative", 60),
|
||||
valign="middle", height=8,
|
||||
))
|
||||
|
||||
def goto_home_timeline(self):
|
||||
self.timeline_generator = api.home_timeline_generator(
|
||||
self.app, self.user, limit=40)
|
||||
promise = self.async_load_timeline(is_initial=True, timeline_name="home")
|
||||
promise.add_done_callback(lambda *args: self.close_overlay())
|
||||
|
||||
def goto_public_timeline(self, local):
|
||||
self.timeline_generator = api.public_timeline_generator(
|
||||
self.app.instance, local=local, limit=40)
|
||||
promise = self.async_load_timeline(is_initial=True, timeline_name="public")
|
||||
promise.add_done_callback(lambda *args: self.close_overlay())
|
||||
|
||||
def show_media(self, status):
|
||||
urls = [m["url"] for m in status.data["media_attachments"]]
|
||||
if urls:
|
||||
@ -364,7 +392,7 @@ class TUI(urwid.Frame):
|
||||
top_widget = urwid.LineBox(widget, title=title)
|
||||
bottom_widget = self.body
|
||||
|
||||
_options = self.default_overlay_options
|
||||
_options = self.default_overlay_options.copy()
|
||||
_options.update(options)
|
||||
|
||||
self.overlay = urwid.Overlay(
|
||||
@ -386,6 +414,12 @@ class TUI(urwid.Frame):
|
||||
if self.exception:
|
||||
self.show_exception(self.exception)
|
||||
|
||||
elif key in ('g', 'G'):
|
||||
logger.info(self.overlay)
|
||||
if not self.overlay:
|
||||
self.show_goto_menu()
|
||||
return
|
||||
|
||||
elif key == 'esc':
|
||||
if self.overlay:
|
||||
self.close_overlay()
|
||||
@ -411,8 +445,29 @@ class StatusSource(urwid.ListBox):
|
||||
class ExceptionStackTrace(urwid.ListBox):
|
||||
"""Shows an exception stack trace."""
|
||||
def __init__(self, ex):
|
||||
lines = traceback.format_exception(etype=type(ex), value=ex, tb=ex.__traceback__) * 3
|
||||
lines = traceback.format_exception(etype=type(ex), value=ex, tb=ex.__traceback__)
|
||||
walker = urwid.SimpleFocusListWalker([
|
||||
urwid.Text(line) for line in lines
|
||||
])
|
||||
super().__init__(walker)
|
||||
|
||||
|
||||
class GotoMenu(urwid.ListBox):
|
||||
signals = [
|
||||
"home_timeline",
|
||||
"local_public_timeline",
|
||||
"global_public_timeline",
|
||||
]
|
||||
|
||||
def __init__(self):
|
||||
actions = list(self.generate_actions())
|
||||
walker = urwid.SimpleFocusListWalker(actions)
|
||||
super().__init__(walker)
|
||||
|
||||
def generate_actions(self):
|
||||
yield Button("Home timeline",
|
||||
on_press=lambda b: self._emit("home_timeline"))
|
||||
yield Button("Local public timeline",
|
||||
on_press=lambda b: self._emit("local_public_timeline"))
|
||||
yield Button("Global public timeline",
|
||||
on_press=lambda b: self._emit("global_public_timeline"))
|
||||
|
Loading…
Reference in New Issue
Block a user