diff --git a/toot/tui/app.py b/toot/tui/app.py index 7f873a5..ec7c174 100644 --- a/toot/tui/app.py +++ b/toot/tui/app.py @@ -11,6 +11,7 @@ from .compose import StatusComposer from .constants import PALETTE from .entities import Status from .timeline import Timeline +from .utils import show_media logger = logging.getLogger(__name__) @@ -171,12 +172,16 @@ class TUI(urwid.Frame): def _source(timeline, status): self.show_status_source(status) + def _media(timeline, status): + self.show_media(status) + urwid.connect_signal(timeline, "focus", self.refresh_footer) urwid.connect_signal(timeline, "reblog", self.async_toggle_reblog) urwid.connect_signal(timeline, "favourite", self.async_toggle_favourite) urwid.connect_signal(timeline, "source", _source) urwid.connect_signal(timeline, "compose", _compose) urwid.connect_signal(timeline, "reply", _reply) + urwid.connect_signal(timeline, "media", _media) def build_timeline(self, statuses): def _close(*args): @@ -281,6 +286,11 @@ class TUI(urwid.Frame): urwid.connect_signal(composer, "post", _post) self.open_overlay(composer, title="Compose status") + def show_media(self, status): + urls = [m["url"] for m in status.data["media_attachments"]] + if urls: + show_media(urls) + def post_status(self, content, warning, visibility, in_reply_to_id): data = api.post_status(self.app, self.user, content, spoiler_text=warning, diff --git a/toot/tui/timeline.py b/toot/tui/timeline.py index 6bbabb2..9240675 100644 --- a/toot/tui/timeline.py +++ b/toot/tui/timeline.py @@ -19,6 +19,7 @@ class Timeline(urwid.Columns): "compose", # Compose a new toot "favourite", # Favourite status "focus", # Focus changed + "media", # Display media attachments "next", # Fetch more statuses "reblog", # Reblog status "reply", # Compose a reply to a status @@ -109,6 +110,10 @@ class Timeline(urwid.Columns): self._emit("favourite", status) return + if key in ("m", "M"): + self._emit("media", status) + return + if key in ("q", "Q"): self._emit("close") return @@ -121,15 +126,15 @@ class Timeline(urwid.Columns): self._emit("thread", status) return + if key in ("u", "U"): + self._emit("source", status) + return + if key in ("v", "V"): if status.data["url"]: webbrowser.open(status.data["url"]) return - if key in ("u", "U"): - self._emit("source", status) - return - return super().keypress(size, key) def append_status(self, status): diff --git a/toot/tui/utils.py b/toot/tui/utils.py index ef0d497..b98b1fc 100644 --- a/toot/tui/utils.py +++ b/toot/tui/utils.py @@ -1,4 +1,6 @@ import re +import shutil +import subprocess from datetime import datetime @@ -39,3 +41,28 @@ def highlight_hashtags(line, attr="hashtag"): (attr, p) if p.startswith("#") else p for p in re.split(HASHTAG_PATTERN, line) ] + + +def show_media(paths): + """ + Attempt to open an image viewer to show given media files. + + FIXME: This is not very thought out, but works for me. + Once settings are implemented, add an option for the user to configure their + prefered media viewer. + """ + viewer = None + potential_viewers = [ + "feh", + "eog", + "display" + ] + for v in potential_viewers: + viewer = shutil.which(v) + if viewer: + break + + if not viewer: + raise Exception("Cannot find an image viewer") + + subprocess.run([viewer] + paths)