Implement character count indicator when composing

Attempts to load max char count from the server on init.

issue #121
This commit is contained in:
Ivan Habunek 2020-01-03 09:15:11 +01:00
parent 5695fdb504
commit 60efc13338
No known key found for this signature in database
GPG Key ID: CDBD63C43A30BB95
4 changed files with 53 additions and 15 deletions

View File

@ -99,6 +99,9 @@ class TUI(urwid.Frame):
self.footer = Footer()
self.footer.set_status("Loading...")
# Default max status length, updated on startup
self.max_toot_chars = 500
self.timeline = None
self.overlay = None
self.exception = None
@ -106,8 +109,9 @@ class TUI(urwid.Frame):
super().__init__(self.body, header=self.header, footer=self.footer)
def run(self):
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_instance())
self.loop.set_alarm_in(0, lambda *args: self.async_load_timeline(
is_initial=True, timeline_name="home"))
self.loop.run()
self.executor.shutdown(wait=False)
@ -269,6 +273,21 @@ class TUI(urwid.Frame):
return self.run_in_thread(_load_statuses,
done_callback=_done_initial if is_initial else _done_next)
def async_load_instance(self):
"""
Attempt to update max_toot_chars from instance data.
Does not work on vanilla Mastodon, works on Pleroma.
See: https://github.com/tootsuite/mastodon/issues/4915
"""
def _load_instance():
return api.get_instance(self.app.instance)
def _done(instance):
if "max_toot_chars" in instance:
self.max_toot_chars
return self.run_in_thread(_load_instance, done_callback=_done)
def refresh_footer(self, timeline):
"""Show status details in footer."""
status, index, count = timeline.get_focused_status_with_counts()
@ -296,7 +315,7 @@ class TUI(urwid.Frame):
def _post(timeline, *args):
self.post_status(*args)
composer = StatusComposer(in_reply_to)
composer = StatusComposer(self.max_toot_chars, in_reply_to)
urwid.connect_signal(composer, "close", _close)
urwid.connect_signal(composer, "post", _post)
self.open_overlay(composer, title="Compose status")

View File

@ -3,6 +3,7 @@ import logging
from .constants import VISIBILITY_OPTIONS
from .widgets import Button, EditBox
logger = logging.getLogger(__name__)
@ -12,17 +13,16 @@ class StatusComposer(urwid.Frame):
"""
signals = ["close", "post"]
def __init__(self, in_reply_to=None):
def __init__(self, max_chars, in_reply_to=None):
self.in_reply_to = in_reply_to
text, edit_pos = '', None
if in_reply_to is not None:
text = '@{} '.format(in_reply_to.account)
edit_pos = len(text)
mentions = ['@{}'.format(m["acct"]) for m in in_reply_to.mentions]
if mentions:
text += '\n\n{}'.format(' '.join(mentions))
self.content_edit = EditBox(edit_text=text, edit_pos=edit_pos,
multiline=True, allow_tab=True)
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)])
self.cw_edit = None
self.cw_add_button = Button("Add content warning",
@ -42,6 +42,23 @@ class StatusComposer(urwid.Frame):
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.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))
def generate_list_items(self):
if self.in_reply_to:
yield urwid.Text(("gray", "Replying to {}".format(self.in_reply_to.account)))
@ -49,6 +66,7 @@ class StatusComposer(urwid.Frame):
yield urwid.Text("Status message")
yield self.content_edit
yield self.char_count
yield urwid.Divider()
if self.cw_edit:

View File

@ -34,6 +34,7 @@ PALETTE = [
('green_selected', 'white,bold', 'dark green'),
('yellow', 'yellow', ''),
('yellow_bold', 'yellow,bold', ''),
('warning', 'light red', ''),
]
VISIBILITY_OPTIONS = [

View File

@ -32,8 +32,8 @@ class SelectableColumns(Clickable, urwid.Columns):
class EditBox(urwid.AttrWrap):
"""Styled edit box."""
def __init__(self, *args, **kwargs):
edit = urwid.Edit(*args, **kwargs)
return super().__init__(edit, "editbox", "editbox_focused")
self.edit = urwid.Edit(*args, **kwargs)
return super().__init__(self.edit, "editbox", "editbox_focused")
class Button(urwid.AttrWrap):