Skip to content

Commit

Permalink
Implement character count indicator when composing
Browse files Browse the repository at this point in the history
Attempts to load max char count from the server on init.

issue #121
  • Loading branch information
ihabunek committed Jan 3, 2020
1 parent 5695fdb commit 60efc13
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 15 deletions.
25 changes: 22 additions & 3 deletions toot/tui/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,19 @@ def __init__(self, app, user):
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

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)

Expand Down Expand Up @@ -269,6 +273,21 @@ def _done_next(statuses):
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()
Expand Down Expand Up @@ -296,7 +315,7 @@ def _close(*args):
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")
Expand Down
38 changes: 28 additions & 10 deletions toot/tui/compose.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

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

logger = logging.getLogger(__name__)


Expand All @@ -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",
Expand All @@ -42,13 +42,31 @@ def __init__(self, in_reply_to=None):
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)))
yield urwid.AttrWrap(urwid.Divider("-"), "gray")

yield urwid.Text("Status message")
yield self.content_edit
yield self.char_count
yield urwid.Divider()

if self.cw_edit:
Expand Down
1 change: 1 addition & 0 deletions toot/tui/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
('green_selected', 'white,bold', 'dark green'),
('yellow', 'yellow', ''),
('yellow_bold', 'yellow,bold', ''),
('warning', 'light red', ''),
]

VISIBILITY_OPTIONS = [
Expand Down
4 changes: 2 additions & 2 deletions toot/tui/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down

0 comments on commit 60efc13

Please sign in to comment.