Skip to content

Commit

Permalink
Add an action to display status links and open them
Browse files Browse the repository at this point in the history
We add a new [L]inks action that opens an overlay window with links
found in the content of selected status. Links are selectable and upon
click/enter we open the web browser at link's URL.
  • Loading branch information
dlax authored and ihabunek committed Apr 15, 2020
1 parent 5fc46d0 commit 28e1281
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 2 deletions.
16 changes: 14 additions & 2 deletions toot/tui/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
from .compose import StatusComposer
from .constants import PALETTE
from .entities import Status
from .overlays import ExceptionStackTrace, GotoMenu, Help, StatusSource
from .overlays import ExceptionStackTrace, GotoMenu, Help, StatusSource, StatusLinks
from .overlays import StatusDeleteConfirmation
from .timeline import Timeline
from .utils import show_media
from .utils import parse_content_links, show_media

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -182,6 +182,9 @@ def _reply(timeline, status):
def _source(timeline, status):
self.show_status_source(status)

def _links(timeline, status):
self.show_links(status)

def _media(timeline, status):
self.show_media(status)

Expand All @@ -197,6 +200,7 @@ def _menu(timeline, status):
urwid.connect_signal(timeline, "reblog", self.async_toggle_reblog)
urwid.connect_signal(timeline, "reply", _reply)
urwid.connect_signal(timeline, "source", _source)
urwid.connect_signal(timeline, "links", _links)

def build_timeline(self, name, statuses):
def _close(*args):
Expand Down Expand Up @@ -302,6 +306,14 @@ def show_status_source(self, status):
title="Status source",
)

def show_links(self, status):
links = parse_content_links(status.data["content"])
self.open_overlay(
widget=StatusLinks(links),
title="Status links",
options={"height": len(links) + 2},
)

def show_exception(self, exception):
self.open_overlay(
widget=ExceptionStackTrace(exception),
Expand Down
15 changes: 15 additions & 0 deletions toot/tui/overlays.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@ def __init__(self, status):
super().__init__(walker)


class StatusLinks(urwid.ListBox):
"""Shows status links."""

def __init__(self, links):

def widget(url, title):
return Button(title or url, on_press=lambda btn: webbrowser.open(url))

walker = urwid.SimpleFocusListWalker(
[widget(url, title) for url, title in links]
)
super().__init__(walker)


class ExceptionStackTrace(urwid.ListBox):
"""Shows an exception stack trace."""
def __init__(self, ex):
Expand Down Expand Up @@ -132,6 +146,7 @@ def link(text, url):
yield urwid.Text(h(" [R] - Reply to current status"))
yield urwid.Text(h(" [S] - Show text marked as sensitive"))
yield urwid.Text(h(" [T] - Show status thread (replies)"))
yield urwid.Text(h(" [L] - Show the status links"))
yield urwid.Text(h(" [U] - Show the status data in JSON as received from the server"))
yield urwid.Text(h(" [V] - Open status in default browser"))
yield urwid.Divider()
Expand Down
6 changes: 6 additions & 0 deletions toot/tui/timeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class Timeline(urwid.Columns):
"reblog", # Reblog status
"reply", # Compose a reply to a status
"source", # Show status source
"links", # Show status links
"thread", # Show thread for status
]

Expand Down Expand Up @@ -140,6 +141,10 @@ def keypress(self, size, key):
self.refresh_status_details()
return

if key in ("l", "L"):
self._emit("links", status)
return

if key in ("t", "T"):
self._emit("thread", status)
return
Expand Down Expand Up @@ -281,6 +286,7 @@ def content_generator(self, status, reblogged_by):
"[F]avourite",
"[V]iew",
"[T]hread" if not self.in_thread else "",
"[L]inks",
"[R]eply",
"So[u]rce",
"[H]elp",
Expand Down
28 changes: 28 additions & 0 deletions toot/tui/utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from html.parser import HTMLParser
import re
import shutil
import subprocess
Expand Down Expand Up @@ -74,3 +75,30 @@ def show_media(paths):
raise Exception("Cannot find an image viewer")

subprocess.run([viewer] + paths)


class LinkParser(HTMLParser):

def reset(self):
super().reset()
self.links = []

def handle_starttag(self, tag, attrs):
if tag == "a":
href, title = None, None
for name, value in attrs:
if name == "href":
href = value
if name == "title":
title = value
if href:
self.links.append((href, title))


def parse_content_links(content):
"""Parse <a> tags from status's `content` and return them as a list of
(href, title), where `title` may be None.
"""
parser = LinkParser()
parser.feed(content)
return parser.links[:]

0 comments on commit 28e1281

Please sign in to comment.