Show status source
This commit is contained in:
parent
2d8199646f
commit
2be8cb8438
4 changed files with 71 additions and 8 deletions
|
@ -3,3 +3,9 @@ https://github.com/CanonicalLtd/subiquity/blob/master/subiquitycore/core.py#L280
|
||||||
|
|
||||||
educational:
|
educational:
|
||||||
https://github.com/TomasTomecek/sen/blob/master/sen/tui/ui.py
|
https://github.com/TomasTomecek/sen/blob/master/sen/tui/ui.py
|
||||||
|
|
||||||
|
check out:
|
||||||
|
https://github.com/rndusr/stig/tree/master/stig/tui
|
||||||
|
|
||||||
|
Questions:
|
||||||
|
* is it possible to make a span a urwid.Text selectable? e.g. for urls and hashtags
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
import urwid
|
import urwid
|
||||||
|
|
||||||
|
@ -8,6 +9,7 @@ from toot import api
|
||||||
from .constants import PALETTE
|
from .constants import PALETTE
|
||||||
from .entities import Status
|
from .entities import Status
|
||||||
from .timeline import Timeline
|
from .timeline import Timeline
|
||||||
|
from .widgets import SelectableText
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -90,6 +92,9 @@ class TUI(urwid.Frame):
|
||||||
self.footer = Footer()
|
self.footer = Footer()
|
||||||
self.footer.set_status("Loading...")
|
self.footer.set_status("Loading...")
|
||||||
|
|
||||||
|
self.timeline = None
|
||||||
|
self.overlay = None
|
||||||
|
|
||||||
super().__init__(self.body, header=self.header, footer=self.footer)
|
super().__init__(self.body, header=self.header, footer=self.footer)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
@ -126,17 +131,18 @@ class TUI(urwid.Frame):
|
||||||
|
|
||||||
def statuses_loaded_initial(self, future):
|
def statuses_loaded_initial(self, future):
|
||||||
# TODO: handle errors in future
|
# TODO: handle errors in future
|
||||||
self.body = Timeline(self, future.result())
|
self.timeline = Timeline(self, future.result())
|
||||||
|
|
||||||
urwid.connect_signal(self.body, "status_focused",
|
urwid.connect_signal(self.timeline, "status_focused",
|
||||||
lambda _, args: self.status_focused(*args))
|
lambda _, args: self.status_focused(*args))
|
||||||
urwid.connect_signal(self.body, "next",
|
urwid.connect_signal(self.timeline, "next",
|
||||||
lambda *args: self.schedule_load_next())
|
lambda *args: self.schedule_load_next())
|
||||||
self.body.status_focused() # Draw first status
|
self.timeline.status_focused() # Draw first status
|
||||||
|
self.body = self.timeline
|
||||||
|
|
||||||
def statuses_loaded_next(self, future):
|
def statuses_loaded_next(self, future):
|
||||||
# TODO: handle errors in future
|
# TODO: handle errors in future
|
||||||
self.body.add_statuses(future.result())
|
self.timeline.add_statuses(future.result())
|
||||||
|
|
||||||
def status_focused(self, status, index, count):
|
def status_focused(self, status, index, count):
|
||||||
self.footer.set_status([
|
self.footer.set_status([
|
||||||
|
@ -144,6 +150,53 @@ class TUI(urwid.Frame):
|
||||||
" - status ", str(index + 1), " of ", str(count),
|
" - status ", str(index + 1), " of ", str(count),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def show_status_source(self, status):
|
||||||
|
self.open_overlay(
|
||||||
|
widget=StatusSource(status),
|
||||||
|
title="Status source",
|
||||||
|
options={
|
||||||
|
"align": 'center',
|
||||||
|
"width": ('relative', 80),
|
||||||
|
"valign": 'middle',
|
||||||
|
"height": ('relative', 80),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
# --- Overlay handling -----------------------------------------------------
|
||||||
|
|
||||||
|
def open_overlay(self, widget, options={}, title=""):
|
||||||
|
top_widget = urwid.LineBox(widget, title=title)
|
||||||
|
bottom_widget = self.body
|
||||||
|
|
||||||
|
self.overlay = urwid.Overlay(
|
||||||
|
top_widget,
|
||||||
|
bottom_widget,
|
||||||
|
**options
|
||||||
|
)
|
||||||
|
self.body = self.overlay
|
||||||
|
|
||||||
|
def close_overlay(self):
|
||||||
|
self.body = self.overlay.bottom_w
|
||||||
|
self.overlay = None
|
||||||
|
|
||||||
|
# --- Keys -----------------------------------------------------------------
|
||||||
|
|
||||||
def unhandled_input(self, key):
|
def unhandled_input(self, key):
|
||||||
if key in ('q', 'Q'):
|
if key in ('q', 'Q'):
|
||||||
|
if self.overlay:
|
||||||
|
self.close_overlay()
|
||||||
|
else:
|
||||||
raise urwid.ExitMainLoop()
|
raise urwid.ExitMainLoop()
|
||||||
|
|
||||||
|
|
||||||
|
class StatusSource(urwid.ListBox):
|
||||||
|
"""Shows status data, as returned by the server, as formatted JSON."""
|
||||||
|
def __init__(self, status):
|
||||||
|
source = json.dumps(status.data, indent=4)
|
||||||
|
lines = source.splitlines()
|
||||||
|
focus_map = {None: "blue_selected"}
|
||||||
|
walker = urwid.SimpleFocusListWalker([
|
||||||
|
urwid.AttrMap(SelectableText(line), None, focus_map)
|
||||||
|
for line in lines
|
||||||
|
])
|
||||||
|
super().__init__(walker)
|
||||||
|
|
|
@ -14,7 +14,7 @@ PALETTE = [
|
||||||
# Colors
|
# Colors
|
||||||
('blue', 'light blue', ''),
|
('blue', 'light blue', ''),
|
||||||
('blue_bold', 'light blue, bold', ''),
|
('blue_bold', 'light blue, bold', ''),
|
||||||
('blue_selected', 'white,bold', 'dark blue'),
|
('blue_selected', 'white', 'dark blue'),
|
||||||
('cyan', 'dark cyan', ''),
|
('cyan', 'dark cyan', ''),
|
||||||
('cyan_bold', 'dark cyan,bold', ''),
|
('cyan_bold', 'dark cyan,bold', ''),
|
||||||
('gray', 'dark gray', ''),
|
('gray', 'dark gray', ''),
|
||||||
|
|
|
@ -26,7 +26,6 @@ class Timeline(urwid.Columns):
|
||||||
def __init__(self, tui, statuses):
|
def __init__(self, tui, statuses):
|
||||||
self.tui = tui
|
self.tui = tui
|
||||||
self.statuses = statuses
|
self.statuses = statuses
|
||||||
self.instance = tui.app.instance
|
|
||||||
|
|
||||||
self.status_list = self.build_status_list(statuses)
|
self.status_list = self.build_status_list(statuses)
|
||||||
self.status_details = self.build_status_details(statuses[0])
|
self.status_details = self.build_status_details(statuses[0])
|
||||||
|
@ -89,6 +88,11 @@ class Timeline(urwid.Columns):
|
||||||
webbrowser.open(status.data["url"])
|
webbrowser.open(status.data["url"])
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if key in ("u", "U"):
|
||||||
|
status = self.get_focused_status()
|
||||||
|
self.tui.show_status_source(status)
|
||||||
|
return
|
||||||
|
|
||||||
return super().keypress(size, key)
|
return super().keypress(size, key)
|
||||||
|
|
||||||
def add_statuses(self, statuses):
|
def add_statuses(self, statuses):
|
||||||
|
|
Loading…
Reference in a new issue