2023-02-11 03:45:15 +01:00
|
|
|
import urwid
|
|
|
|
|
|
|
|
from toot import api
|
|
|
|
from toot.exceptions import ApiError
|
|
|
|
from toot.utils import format_content
|
|
|
|
from .utils import highlight_hashtags, parse_datetime
|
2023-02-15 04:21:04 +01:00
|
|
|
from .widgets import Button, CheckBox, RadioButton
|
2023-02-11 03:45:15 +01:00
|
|
|
|
|
|
|
|
|
|
|
class Poll(urwid.ListBox):
|
|
|
|
"""View and vote on a poll"""
|
|
|
|
|
|
|
|
def __init__(self, app, user, status):
|
|
|
|
self.status = status
|
|
|
|
self.app = app
|
|
|
|
self.user = user
|
|
|
|
self.poll = status.data.get("poll")
|
|
|
|
self.button_group = []
|
|
|
|
|
|
|
|
self.setup_listbox()
|
|
|
|
|
|
|
|
def setup_listbox(self):
|
|
|
|
actions = list(self.generate_contents(self.status))
|
|
|
|
walker = urwid.SimpleListWalker(actions)
|
|
|
|
super().__init__(walker)
|
|
|
|
|
|
|
|
def build_linebox(self, contents):
|
|
|
|
contents = urwid.Pile(list(contents))
|
|
|
|
contents = urwid.Padding(contents, left=1, right=1)
|
|
|
|
return urwid.LineBox(contents)
|
|
|
|
|
|
|
|
def vote(self, button):
|
|
|
|
poll = self.status.data.get("poll")
|
|
|
|
choices = []
|
|
|
|
for idx, b in enumerate(self.button_group):
|
2023-02-15 04:21:04 +01:00
|
|
|
if b.get_state():
|
2023-02-11 03:45:15 +01:00
|
|
|
choices.append(idx)
|
|
|
|
|
|
|
|
if len(choices):
|
|
|
|
try:
|
|
|
|
response = api.vote(self.app, self.user, poll["id"], choices=choices)
|
|
|
|
self.status.data["poll"] = response
|
|
|
|
self.poll["voted"] = True
|
|
|
|
self.poll["own_votes"] = choices
|
|
|
|
except ApiError:
|
|
|
|
pass # FIXME error reporting?
|
|
|
|
finally:
|
|
|
|
self.setup_listbox()
|
|
|
|
|
|
|
|
def generate_poll_detail(self, status):
|
|
|
|
poll = self.poll
|
|
|
|
|
|
|
|
if poll:
|
|
|
|
self.button_group = [] # button group
|
|
|
|
for idx, option in enumerate(poll["options"]):
|
|
|
|
voted_for = (
|
|
|
|
poll["voted"] and poll["own_votes"] and idx in poll["own_votes"]
|
|
|
|
)
|
|
|
|
|
|
|
|
if poll["voted"] or poll["expired"]:
|
|
|
|
prefix = " ✓ " if voted_for else " "
|
|
|
|
yield urwid.Text(("gray", prefix + f'{option["title"]}'))
|
|
|
|
else:
|
|
|
|
if poll["multiple"]:
|
2023-02-15 04:21:04 +01:00
|
|
|
cb = CheckBox(f'{option["title"]}')
|
2023-02-11 03:45:15 +01:00
|
|
|
self.button_group.append(cb)
|
|
|
|
yield cb
|
|
|
|
else:
|
2023-02-15 04:21:04 +01:00
|
|
|
yield RadioButton(self.button_group, f'{option["title"]}')
|
2023-02-11 03:45:15 +01:00
|
|
|
|
|
|
|
yield urwid.Divider()
|
|
|
|
|
|
|
|
poll_detail = "Poll · {} votes".format(poll["votes_count"])
|
|
|
|
|
|
|
|
if poll["expired"]:
|
|
|
|
poll_detail += " · Closed"
|
|
|
|
|
|
|
|
if poll["expires_at"]:
|
|
|
|
expires_at = parse_datetime(poll["expires_at"]).strftime(
|
|
|
|
"%Y-%m-%d %H:%M"
|
|
|
|
)
|
|
|
|
poll_detail += " · Closes on {}".format(expires_at)
|
|
|
|
|
|
|
|
yield urwid.Text(("gray", poll_detail))
|
|
|
|
|
|
|
|
def generate_contents(self, status):
|
|
|
|
yield urwid.Divider()
|
|
|
|
for line in format_content(status.data["content"]):
|
|
|
|
yield (urwid.Text(highlight_hashtags(line, set())))
|
|
|
|
|
|
|
|
yield urwid.Divider()
|
|
|
|
yield (self.build_linebox(self.generate_poll_detail(status)))
|
|
|
|
yield urwid.Divider()
|
|
|
|
|
|
|
|
if self.poll["voted"]:
|
|
|
|
yield urwid.Text(("grey", "< Already Voted >"))
|
|
|
|
elif not self.poll["expired"]:
|
|
|
|
yield Button("Vote", on_press=self.vote)
|