You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

274 lines
7.0 KiB

package ui
import (
"fmt"
"time"
"github.com/RasmusLindroth/go-mastodon"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
)
var durations = []string{
"5 minutes",
"30 minutes",
"1 hour",
"6 hours",
"1 day",
"3 days",
"7 days",
}
var durationsTime = map[string]int64{
"5 minutes": 60 * 50,
"30 minutes": 60 * 30,
"1 hour": 60 * 60,
"6 hours": 60 * 60 * 6,
"1 day": 60 * 60 * 24,
"3 days": 60 * 60 * 24 * 3,
"7 days": 60 * 60 * 24 * 7,
}
type PollView struct {
tutView *TutView
shared *Shared
View *tview.Flex
info *tview.TextView
expiration *tview.DropDown
controls *tview.Flex
list *tview.List
poll *mastodon.TootPoll
scrollSleep *scrollSleep
numOptions int
numChars int
}
func NewPollView(tv *TutView) *PollView {
options, chars := tv.tut.Client.GetPollOptions()
p := &PollView{
tutView: tv,
shared: tv.Shared,
info: NewTextView(tv.tut.Config),
expiration: NewDropDown(tv.tut.Config),
controls: NewControlView(tv.tut.Config),
list: NewList(tv.tut.Config),
numOptions: options,
numChars: chars,
}
p.scrollSleep = NewScrollSleep(p.Next, p.Prev)
p.Reset()
p.View = pollViewUI(p)
return p
}
func pollViewUI(p *PollView) *tview.Flex {
var items []Control
items = append(items, NewControl(p.tutView.tut.Config, p.tutView.tut.Config.Input.PollAdd, true))
items = append(items, NewControl(p.tutView.tut.Config, p.tutView.tut.Config.Input.PollEdit, true))
items = append(items, NewControl(p.tutView.tut.Config, p.tutView.tut.Config.Input.PollDelete, true))
items = append(items, NewControl(p.tutView.tut.Config, p.tutView.tut.Config.Input.PollMultiToggle, true))
items = append(items, NewControl(p.tutView.tut.Config, p.tutView.tut.Config.Input.PollExpiration, true))
p.controls.Clear()
for i, item := range items {
if i < len(items)-1 {
p.controls.AddItem(NewControlButton(p.tutView, item), item.Len+1, 0, false)
} else {
p.controls.AddItem(NewControlButton(p.tutView, item), item.Len, 0, false)
}
}
p.expiration.SetLabel("Expiration: ")
p.expiration.SetOptions(durations, p.expirationSelected)
p.expiration.SetCurrentOption(4)
r := tview.NewFlex().SetDirection(tview.FlexRow)
if p.tutView.tut.Config.General.TerminalTitle < 2 {
r.AddItem(p.shared.Top.View, 1, 0, false)
}
r.AddItem(tview.NewFlex().SetDirection(tview.FlexColumn).
AddItem(tview.NewFlex().SetDirection(tview.FlexRow).
AddItem(p.list, 0, 10, false), 0, 2, false).
AddItem(tview.NewBox(), 2, 0, false).
AddItem(tview.NewFlex().SetDirection(tview.FlexRow).
AddItem(p.expiration, 1, 0, false).
AddItem(p.info, 3, 0, false), 0, 1, false), 0, 1, false).
AddItem(p.controls, 1, 0, false).
AddItem(p.shared.Bottom.View, 2, 0, false)
return r
}
func (p *PollView) Reset() {
p.poll = &mastodon.TootPoll{
Options: []string{},
ExpiresInSeconds: durationsTime[durations[4]],
Multiple: false,
HideTotals: false,
}
p.list.Clear()
p.redrawInfo()
}
func (p *PollView) AddPoll(np *mastodon.Poll) {
p.poll = &mastodon.TootPoll{
Options: []string{},
ExpiresInSeconds: durationsTime[durations[4]],
Multiple: false,
HideTotals: false,
}
for _, opt := range np.Options {
p.poll.Options = append(p.poll.Options, opt.Title)
p.list.AddItem(opt.Title, "", 0, nil)
}
p.poll.Multiple = np.Multiple
diff := time.Until(np.ExpiresAt)
p.poll.ExpiresInSeconds = int64(diff.Seconds())
p.redrawInfo()
}
func (p *PollView) HasPoll() bool {
return p.list.GetItemCount() > 1
}
func (p *PollView) GetPoll() *mastodon.TootPoll {
options := []string{}
for i := 0; i < p.list.GetItemCount(); i++ {
m, _ := p.list.GetItemText(i)
options = append(options, m)
}
return &mastodon.TootPoll{
Options: options,
ExpiresInSeconds: p.poll.ExpiresInSeconds,
Multiple: p.poll.Multiple,
HideTotals: false,
}
}
func (p *PollView) redrawInfo() {
content := fmt.Sprintf("Multiple answers: %v", p.poll.Multiple)
p.info.SetText(content)
}
func (p *PollView) Prev() {
index := p.list.GetCurrentItem()
if index-1 >= 0 {
p.list.SetCurrentItem(index - 1)
}
}
func (p *PollView) Next() {
index := p.list.GetCurrentItem()
if index+1 < p.list.GetItemCount() {
p.list.SetCurrentItem(index + 1)
}
}
func (p *PollView) Add() {
if p.list.GetItemCount() > p.numOptions-1 {
p.tutView.ShowError(fmt.Sprintf("You can only have a maximum of %d options.", p.numOptions))
return
}
if p.tutView.tut.Config.General.UseInternalEditor {
p.tutView.EditorView.Init("", p.numChars, true, func(input string) {
p.add(input, nil)
})
} else {
text, err := OpenEditorLengthLimit(p.tutView, "", p.numChars)
p.add(text, err)
}
}
func (p *PollView) add(text string, err error) {
if err != nil {
p.tutView.ShowError(
fmt.Sprintf("Couldn't open editor. Error: %v", err),
)
return
}
if len(text) == 0 {
return
}
p.list.AddItem(text, "", 0, nil)
p.list.SetCurrentItem(
p.list.GetItemCount() - 1,
)
}
func (p *PollView) Edit() {
if p.list.GetItemCount() == 0 {
return
}
text, _ := p.list.GetItemText(p.list.GetCurrentItem())
if p.tutView.tut.Config.General.UseInternalEditor {
p.tutView.EditorView.Init(text, p.numChars, true, func(input string) {
p.edit(input, nil)
})
} else {
text, err := OpenEditorLengthLimit(p.tutView, text, p.numChars)
p.edit(text, err)
}
}
func (p *PollView) edit(text string, err error) {
if err != nil {
p.tutView.ShowError(
fmt.Sprintf("Couldn't open editor. Error: %v", err),
)
return
}
if len(text) == 0 {
return
}
p.list.SetItemText(p.list.GetCurrentItem(), text, "")
}
func (p *PollView) Delete() {
if p.list.GetItemCount() == 0 {
return
}
item := p.list.GetCurrentItem()
p.list.RemoveItem(item)
if p.list.GetCurrentItem() < 0 && p.list.GetItemCount() > 0 {
p.list.SetCurrentItem(0)
}
}
func (p *PollView) ToggleMultiple() {
p.poll.Multiple = !p.poll.Multiple
p.redrawInfo()
}
func (p *PollView) expirationSelected(s string, index int) {
_, v := p.expiration.GetCurrentOption()
for k, dur := range durationsTime {
if v == k {
p.poll.ExpiresInSeconds = dur
break
}
}
p.exitExpiration()
}
func (p *PollView) expirationInput(event *tcell.EventKey) *tcell.EventKey {
if p.tutView.tut.Config.Input.GlobalDown.Match(event.Key(), event.Rune()) {
return tcell.NewEventKey(tcell.KeyDown, 0, tcell.ModNone)
}
if p.tutView.tut.Config.Input.GlobalUp.Match(event.Key(), event.Rune()) {
return tcell.NewEventKey(tcell.KeyUp, 0, tcell.ModNone)
}
if p.tutView.tut.Config.Input.GlobalExit.Match(event.Key(), event.Rune()) ||
p.tutView.tut.Config.Input.GlobalBack.Match(event.Key(), event.Rune()) {
p.exitExpiration()
return nil
}
return event
}
func (p *PollView) FocusExpiration() {
p.tutView.tut.App.SetInputCapture(p.expirationInput)
p.tutView.tut.App.SetFocus(p.expiration)
ev := tcell.NewEventKey(tcell.KeyDown, 0, tcell.ModNone)
p.tutView.tut.App.QueueEvent(ev)
}
func (p *PollView) exitExpiration() {
p.tutView.tut.App.SetInputCapture(p.tutView.Input)
p.tutView.tut.App.SetFocus(p.tutView.View)
}