Toot-Mastodon-CLI-TUI-clien.../toot/tui/compose.py

145 lines
4.9 KiB
Python
Raw Normal View History

2019-08-27 10:02:13 +02:00
import urwid
import logging
2019-08-27 14:16:14 +02:00
from .constants import VISIBILITY_OPTIONS
2019-08-30 12:28:03 +02:00
from .widgets import Button, EditBox
2019-08-27 10:02:13 +02:00
logger = logging.getLogger(__name__)
class StatusComposer(urwid.Frame):
2019-08-27 14:16:14 +02:00
"""
UI for compose and posting a status message.
"""
2019-08-27 10:02:13 +02:00
signals = ["close", "post"]
def __init__(self, max_chars, in_reply_to=None):
2019-08-29 11:01:49 +02:00
self.in_reply_to = in_reply_to
self.max_chars = max_chars
text = self.get_initial_text(in_reply_to)
self.content_edit = EditBox(
edit_text=text, edit_pos=len(text), multiline=True, allow_tab=True)
urwid.connect_signal(self.content_edit.edit, "change", self.text_changed)
self.char_count = urwid.Text(["0/{}".format(max_chars)])
2019-08-27 14:16:14 +02:00
self.cw_edit = None
self.cw_add_button = Button("Add content warning",
on_press=self.add_content_warning)
self.cw_remove_button = Button("Remove content warning",
on_press=self.remove_content_warning)
self.visibility = "public"
self.visibility_button = Button("Visibility: {}".format(self.visibility),
on_press=self.choose_visibility)
2019-08-27 10:02:13 +02:00
2019-08-27 14:16:14 +02:00
self.post_button = Button("Post", on_press=self.post)
self.cancel_button = Button("Cancel", on_press=self.close)
contents = list(self.generate_list_items())
2019-08-27 10:02:13 +02:00
self.walker = urwid.SimpleListWalker(contents)
self.listbox = urwid.ListBox(self.walker)
return super().__init__(self.listbox)
def get_initial_text(self, in_reply_to):
if not in_reply_to:
return ""
text = '@{} '.format(in_reply_to.original.account)
mentions = ['@{}'.format(m["acct"]) for m in in_reply_to.mentions]
if mentions:
text += '\n\n{}'.format(' '.join(mentions))
return text
def text_changed(self, edit, text):
count = self.max_chars - len(text)
text = "{}/{}".format(count, self.max_chars)
color = "warning" if count < 0 else ""
self.char_count.set_text((color, text))
2019-08-27 14:16:14 +02:00
def generate_list_items(self):
2019-08-29 11:01:49 +02:00
if self.in_reply_to:
yield urwid.Text(("gray", "Replying to {}".format(self.in_reply_to.original.account)))
2019-08-29 11:01:49 +02:00
yield urwid.AttrWrap(urwid.Divider("-"), "gray")
yield urwid.Text("Status message")
2019-08-27 14:16:14 +02:00
yield self.content_edit
yield self.char_count
2019-08-27 14:16:14 +02:00
yield urwid.Divider()
2019-08-27 10:02:13 +02:00
2019-08-27 14:16:14 +02:00
if self.cw_edit:
2019-08-29 11:01:49 +02:00
yield urwid.Text("Content warning")
2019-08-27 14:16:14 +02:00
yield self.cw_edit
yield urwid.Divider()
yield self.cw_remove_button
else:
yield self.cw_add_button
yield self.visibility_button
yield self.post_button
yield self.cancel_button
def refresh(self):
self.walker = urwid.SimpleListWalker(list(self.generate_list_items()))
self.listbox.body = self.walker
def choose_visibility(self, *args):
list_items = [urwid.Text("Choose status visibility:")]
for visibility, caption, description in VISIBILITY_OPTIONS:
text = "{} - {}".format(caption, description)
button = Button(text, on_press=self.set_visibility, user_data=visibility)
list_items.append(button)
self.walker = urwid.SimpleListWalker(list_items)
self.listbox.body = self.walker
# Initially focus currently chosen visibility
focus_map = {v[0]: n + 1 for n, v in enumerate(VISIBILITY_OPTIONS)}
focus = focus_map.get(self.visibility, 1)
self.walker.set_focus(focus)
def set_visibility(self, widget, visibility):
self.visibility = visibility
self.visibility_button.set_label("Visibility: {}".format(self.visibility))
self.refresh()
self.walker.set_focus(7 if self.cw_edit else 4)
def add_content_warning(self, button):
2019-08-30 15:31:57 +02:00
self.cw_edit = EditBox(multiline=True, allow_tab=True)
2019-08-27 14:16:14 +02:00
self.refresh()
self.walker.set_focus(4)
def remove_content_warning(self, button):
self.cw_edit = None
self.refresh()
self.walker.set_focus(3)
2019-08-27 10:02:13 +02:00
def set_error_message(self, msg):
self.footer = urwid.Text(("footer_message_error", msg))
2019-08-27 14:16:14 +02:00
def clear_error_message(self):
self.footer = None
2019-08-27 10:02:13 +02:00
def post(self, button):
self.clear_error_message()
# Don't lstrip content to avoid removing intentional leading whitespace
# However, do strip both sides to check if there is any content there
2019-08-27 14:16:14 +02:00
content = self.content_edit.edit_text.rstrip()
2019-08-27 10:02:13 +02:00
content = None if not content.strip() else content
2019-08-27 14:16:14 +02:00
warning = self.cw_edit.edit_text.rstrip() if self.cw_edit else ""
2019-08-27 10:02:13 +02:00
warning = None if not warning.strip() else warning
if not content:
self.set_error_message("Cannot post an empty message")
return
2019-08-29 11:01:49 +02:00
in_reply_to_id = self.in_reply_to.id if self.in_reply_to else None
self._emit("post", content, warning, self.visibility, in_reply_to_id)
2019-08-27 10:02:13 +02:00
def close(self, button):
self._emit("close")