Skip to content

Commit

Permalink
tui: honour user's default visibility preference
Browse files Browse the repository at this point in the history
Mastodon allows the user to configure a default visibility which should
apply to all clients.  This setting is returned by the
/api/v1/preferences method.

Fetch the user preferences when the TUI starts, and use it to set the
default visibility when composing a new toot.  The preference can be
overridden by a new command-line option, toot tui --default-visibility=.
If neither the preference nor the option are set, fall back to
get_default_visibility().
  • Loading branch information
llfw committed Dec 31, 2023
1 parent 4e55fba commit 5dd53b1
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 6 deletions.
4 changes: 4 additions & 0 deletions toot/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,10 @@ def get_instance(base_url: str) -> Response:
return http.anon_get(url)


def get_preferences(app, user) -> Response:
return http.get(app, user, '/api/v1/preferences')


def get_lists(app, user):
return http.get(app, user, "/api/v1/lists").json()

Expand Down
9 changes: 8 additions & 1 deletion toot/cli/tui.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import click

from typing import Optional
from toot.cli import TUI_COLORS, Context, cli, pass_context
from toot.cli import TUI_COLORS, VISIBILITY_CHOICES, Context, cli, pass_context
from toot.cli.validators import validate_tui_colors
from toot.tui.app import TUI, TuiOptions

Expand All @@ -24,12 +24,18 @@
help=f"""Number of colors to use, one of {COLOR_OPTIONS}, defaults to 16 if
using --color, and 1 if using --no-color."""
)
@click.option(
"-v", "--default-visibility",
type=click.Choice(VISIBILITY_CHOICES),
help="Default visibility when posting new toots; overrides the server-side preference"
)
@pass_context
def tui(
ctx: Context,
colors: Optional[int],
media_viewer: Optional[str],
relative_datetimes: bool,
default_visibility: Optional[str]
):
"""Launches the toot terminal user interface"""
if colors is None:
Expand All @@ -39,6 +45,7 @@ def tui(
colors=colors,
media_viewer=media_viewer,
relative_datetimes=relative_datetimes,
default_visibility=default_visibility
)
tui = TUI.create(ctx.app, ctx.user, options)
tui.run()
26 changes: 25 additions & 1 deletion toot/tui/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class TuiOptions(NamedTuple):
colors: int
media_viewer: Optional[str]
relative_datetimes: bool
default_visibility: Optional[bool]


class Header(urwid.WidgetWrap):
Expand Down Expand Up @@ -137,11 +138,13 @@ def __init__(self, app, user, screen, options: TuiOptions):
self.can_translate = False
self.account = None
self.followed_accounts = []
self.preferences = {}

super().__init__(self.body, header=self.header, footer=self.footer)

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_preferences())
self.loop.set_alarm_in(0, lambda *args: self.async_load_timeline(
is_initial=True, timeline_name="home"))
self.loop.set_alarm_in(0, lambda *args: self.async_load_followed_accounts())
Expand Down Expand Up @@ -326,6 +329,19 @@ def _done(instance):

return self.run_in_thread(_load_instance, done_callback=_done)

def async_load_preferences(self):
"""
Attempt to update user preferences from instance.
https://docs.joinmastodon.org/methods/preferences/
"""
def _load_preferences():
return api.get_preferences(self.app, self.user).json()

def _done(preferences):
self.preferences = preferences

return self.run_in_thread(_load_preferences, done_callback=_done)

def async_load_followed_accounts(self):
def _load_accounts():
try:
Expand Down Expand Up @@ -400,7 +416,15 @@ def _close(*args):
def _post(timeline, *args):
self.post_status(*args)

composer = StatusComposer(self.max_toot_chars, self.user.username, in_reply_to)
# If the user specified --default-visibility, use that; otherwise,
# try to use the server-side default visibility. If that fails, fall
# back to get_default_visibility().
visibility = (self.options.default_visibility or
self.preferences.get('posting:default:visibility',
get_default_visibility()))

composer = StatusComposer(self.max_toot_chars, self.user.username,
visibility, in_reply_to)
urwid.connect_signal(composer, "close", _close)
urwid.connect_signal(composer, "post", _post)
self.open_overlay(composer, title="Compose status")
Expand Down
6 changes: 2 additions & 4 deletions toot/tui/compose.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import urwid
import logging

from toot.cli import get_default_visibility

from .constants import VISIBILITY_OPTIONS
from .widgets import Button, EditBox

Expand All @@ -15,7 +13,7 @@ class StatusComposer(urwid.Frame):
"""
signals = ["close", "post"]

def __init__(self, max_chars, username, in_reply_to=None):
def __init__(self, max_chars, username, visibility, in_reply_to=None):
self.in_reply_to = in_reply_to
self.max_chars = max_chars
self.username = username
Expand All @@ -34,7 +32,7 @@ def __init__(self, max_chars, username, in_reply_to=None):
on_press=self.remove_content_warning)

self.visibility = (
in_reply_to.visibility if in_reply_to else get_default_visibility()
in_reply_to.visibility if in_reply_to else visibility
)
self.visibility_button = Button("Visibility: {}".format(self.visibility),
on_press=self.choose_visibility)
Expand Down

0 comments on commit 5dd53b1

Please sign in to comment.