mirror of
https://github.com/ihabunek/toot
synced 2025-02-13 18:40:47 +01:00
tui: honour user's default visibility preference
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().
This commit is contained in:
parent
4e55fba15e
commit
5dd53b1b9c
@ -618,6 +618,10 @@ def get_instance(base_url: str) -> Response:
|
|||||||
return http.anon_get(url)
|
return http.anon_get(url)
|
||||||
|
|
||||||
|
|
||||||
|
def get_preferences(app, user) -> Response:
|
||||||
|
return http.get(app, user, '/api/v1/preferences')
|
||||||
|
|
||||||
|
|
||||||
def get_lists(app, user):
|
def get_lists(app, user):
|
||||||
return http.get(app, user, "/api/v1/lists").json()
|
return http.get(app, user, "/api/v1/lists").json()
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import click
|
import click
|
||||||
|
|
||||||
from typing import Optional
|
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.cli.validators import validate_tui_colors
|
||||||
from toot.tui.app import TUI, TuiOptions
|
from toot.tui.app import TUI, TuiOptions
|
||||||
|
|
||||||
@ -24,12 +24,18 @@ COLOR_OPTIONS = ", ".join(TUI_COLORS.keys())
|
|||||||
help=f"""Number of colors to use, one of {COLOR_OPTIONS}, defaults to 16 if
|
help=f"""Number of colors to use, one of {COLOR_OPTIONS}, defaults to 16 if
|
||||||
using --color, and 1 if using --no-color."""
|
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
|
@pass_context
|
||||||
def tui(
|
def tui(
|
||||||
ctx: Context,
|
ctx: Context,
|
||||||
colors: Optional[int],
|
colors: Optional[int],
|
||||||
media_viewer: Optional[str],
|
media_viewer: Optional[str],
|
||||||
relative_datetimes: bool,
|
relative_datetimes: bool,
|
||||||
|
default_visibility: Optional[str]
|
||||||
):
|
):
|
||||||
"""Launches the toot terminal user interface"""
|
"""Launches the toot terminal user interface"""
|
||||||
if colors is None:
|
if colors is None:
|
||||||
@ -39,6 +45,7 @@ def tui(
|
|||||||
colors=colors,
|
colors=colors,
|
||||||
media_viewer=media_viewer,
|
media_viewer=media_viewer,
|
||||||
relative_datetimes=relative_datetimes,
|
relative_datetimes=relative_datetimes,
|
||||||
|
default_visibility=default_visibility
|
||||||
)
|
)
|
||||||
tui = TUI.create(ctx.app, ctx.user, options)
|
tui = TUI.create(ctx.app, ctx.user, options)
|
||||||
tui.run()
|
tui.run()
|
||||||
|
@ -31,6 +31,7 @@ class TuiOptions(NamedTuple):
|
|||||||
colors: int
|
colors: int
|
||||||
media_viewer: Optional[str]
|
media_viewer: Optional[str]
|
||||||
relative_datetimes: bool
|
relative_datetimes: bool
|
||||||
|
default_visibility: Optional[bool]
|
||||||
|
|
||||||
|
|
||||||
class Header(urwid.WidgetWrap):
|
class Header(urwid.WidgetWrap):
|
||||||
@ -137,11 +138,13 @@ class TUI(urwid.Frame):
|
|||||||
self.can_translate = False
|
self.can_translate = False
|
||||||
self.account = None
|
self.account = None
|
||||||
self.followed_accounts = []
|
self.followed_accounts = []
|
||||||
|
self.preferences = {}
|
||||||
|
|
||||||
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):
|
||||||
self.loop.set_alarm_in(0, lambda *args: self.async_load_instance())
|
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(
|
self.loop.set_alarm_in(0, lambda *args: self.async_load_timeline(
|
||||||
is_initial=True, timeline_name="home"))
|
is_initial=True, timeline_name="home"))
|
||||||
self.loop.set_alarm_in(0, lambda *args: self.async_load_followed_accounts())
|
self.loop.set_alarm_in(0, lambda *args: self.async_load_followed_accounts())
|
||||||
@ -326,6 +329,19 @@ class TUI(urwid.Frame):
|
|||||||
|
|
||||||
return self.run_in_thread(_load_instance, done_callback=_done)
|
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 async_load_followed_accounts(self):
|
||||||
def _load_accounts():
|
def _load_accounts():
|
||||||
try:
|
try:
|
||||||
@ -400,7 +416,15 @@ class TUI(urwid.Frame):
|
|||||||
def _post(timeline, *args):
|
def _post(timeline, *args):
|
||||||
self.post_status(*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, "close", _close)
|
||||||
urwid.connect_signal(composer, "post", _post)
|
urwid.connect_signal(composer, "post", _post)
|
||||||
self.open_overlay(composer, title="Compose status")
|
self.open_overlay(composer, title="Compose status")
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import urwid
|
import urwid
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from toot.cli import get_default_visibility
|
|
||||||
|
|
||||||
from .constants import VISIBILITY_OPTIONS
|
from .constants import VISIBILITY_OPTIONS
|
||||||
from .widgets import Button, EditBox
|
from .widgets import Button, EditBox
|
||||||
|
|
||||||
@ -15,7 +13,7 @@ class StatusComposer(urwid.Frame):
|
|||||||
"""
|
"""
|
||||||
signals = ["close", "post"]
|
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.in_reply_to = in_reply_to
|
||||||
self.max_chars = max_chars
|
self.max_chars = max_chars
|
||||||
self.username = username
|
self.username = username
|
||||||
@ -34,7 +32,7 @@ class StatusComposer(urwid.Frame):
|
|||||||
on_press=self.remove_content_warning)
|
on_press=self.remove_content_warning)
|
||||||
|
|
||||||
self.visibility = (
|
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),
|
self.visibility_button = Button("Visibility: {}".format(self.visibility),
|
||||||
on_press=self.choose_visibility)
|
on_press=self.choose_visibility)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user