diff --git a/toot/tui/app.py b/toot/tui/app.py index 650f771..590aef8 100644 --- a/toot/tui/app.py +++ b/toot/tui/app.py @@ -113,6 +113,7 @@ class TUI(urwid.Frame): def run(self): self.loop.set_alarm_in(0, lambda *args: self.async_load_instance()) + self.loop.set_alarm_in(0, lambda *args: self.async_load_followed_tags()) self.loop.set_alarm_in(0, lambda *args: self.async_load_timeline( is_initial=True, timeline_name="home")) self.loop.run() @@ -237,7 +238,7 @@ class TUI(urwid.Frame): self.loop.set_alarm_in(5, lambda *args: self.footer.clear_message()) config.save_config(self.config) - timeline = Timeline(name, statuses, self.can_translate) + timeline = Timeline(name, statuses, self.can_translate, self.followed_tags) self.connect_default_timeline_signals(timeline) urwid.connect_signal(timeline, "next", _next) @@ -266,8 +267,9 @@ class TUI(urwid.Frame): statuses = ancestors + [status] + descendants focus = len(ancestors) - timeline = Timeline("thread", statuses, self.can_translate, focus, - is_thread=True) + timeline = Timeline("thread", statuses, self.can_translate, + self.followed_tags, focus, is_thread=True) + self.connect_default_timeline_signals(timeline) urwid.connect_signal(timeline, "close", _close) @@ -334,6 +336,28 @@ class TUI(urwid.Frame): return self.run_in_thread(_load_instance, done_callback=_done) + def async_load_followed_tags(self): + def _load_tag_list(): + logger.info("Loading tags") + try: + return api.followed_tags(self.app, self.user) + except: + # not supported by all Mastodon servers so fail silently if necessary + return [] + + def _done_tag_list(tags): + if len(tags) > 0: + self.followed_tags = [t["name"] for t in tags] + else: + self.followed_tags = [] + logger.info("Loaded tags. Followed tags = {}".format(self.followed_tags)) + + self.run_in_thread( + _load_tag_list, done_callback=_done_tag_list + ) + + + def refresh_footer(self, timeline): """Show status details in footer.""" status, index, count = timeline.get_focused_status_with_counts() diff --git a/toot/tui/constants.py b/toot/tui/constants.py index cbf257e..e866e34 100644 --- a/toot/tui/constants.py +++ b/toot/tui/constants.py @@ -19,6 +19,7 @@ PALETTE = [ # Functional ('hashtag', 'light cyan,bold', ''), + ('followed_hashtag', 'yellow,bold', ''), ('link', ',italics', ''), ('link_focused', ',italics', 'dark magenta'), diff --git a/toot/tui/timeline.py b/toot/tui/timeline.py index 43f927a..7d1e601 100644 --- a/toot/tui/timeline.py +++ b/toot/tui/timeline.py @@ -36,16 +36,17 @@ class Timeline(urwid.Columns): "clear-screen", # Clear the screen (used internally) ] - def __init__(self, name, statuses, can_translate, focus=0, is_thread=False): + def __init__(self, name, statuses, can_translate, followed_tags=[], focus=0, is_thread=False): self.name = name self.is_thread = is_thread self.statuses = statuses self.can_translate = can_translate self.status_list = self.build_status_list(statuses, focus=focus) + self.followed_tags = followed_tags try: - self.status_details = StatusDetails(statuses[focus], is_thread, can_translate) + self.status_details = StatusDetails(statuses[focus], is_thread, can_translate, followed_tags) except IndexError: - self.status_details = StatusDetails(None, is_thread, can_translate) + self.status_details = StatusDetails(None, is_thread, can_translate, followed_tags) super().__init__([ ("weight", 40, self.status_list), @@ -103,7 +104,7 @@ class Timeline(urwid.Columns): self.draw_status_details(status) def draw_status_details(self, status): - self.status_details = StatusDetails(status, self.is_thread, self.can_translate) + self.status_details = StatusDetails(status, self.is_thread, self.can_translate, self.followed_tags) self.contents[2] = urwid.Padding(self.status_details, left=1), ("weight", 60, False) def keypress(self, size, key): @@ -245,7 +246,7 @@ class Timeline(urwid.Columns): class StatusDetails(urwid.Pile): - def __init__(self, status, in_thread, can_translate=False): + def __init__(self, status, in_thread, can_translate=False, followed_tags=[]): """ Parameters ---------- @@ -257,6 +258,7 @@ class StatusDetails(urwid.Pile): """ self.in_thread = in_thread self.can_translate = can_translate + self.followed_tags = followed_tags reblogged_by = status.author if status and status.reblog else None widget_list = list(self.content_generator(status.original, reblogged_by) if status else ()) @@ -284,7 +286,7 @@ class StatusDetails(urwid.Pile): else: content = status.translation if status.show_translation else status.data["content"] for line in format_content(content): - yield ("pack", urwid.Text(highlight_hashtags(line))) + yield ("pack", urwid.Text(highlight_hashtags(line, self.followed_tags))) media = status.data["media_attachments"] if media: diff --git a/toot/tui/utils.py b/toot/tui/utils.py index a9ab122..727788e 100644 --- a/toot/tui/utils.py +++ b/toot/tui/utils.py @@ -51,11 +51,18 @@ def highlight_keys(text, high_attr, low_attr=""): return list(_gen()) -def highlight_hashtags(line, attr="hashtag"): - return [ - (attr, p) if p.startswith("#") else p - for p in re.split(HASHTAG_PATTERN, line) - ] +def highlight_hashtags(line, followed_tags, attr="hashtag",\ + followed_attr="followed_hashtag"): + hline = [] + for p in re.split(HASHTAG_PATTERN, line): + if p.startswith("#"): + if p[1:].lower() in (t.lower() for t in followed_tags): + hline.append((followed_attr,p)) + else: + hline.append((attr,p)) + else: + hline.append(p) + return hline def show_media(paths):