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.

430 lines
11 KiB

package ui
import (
"fmt"
"github.com/RasmusLindroth/go-mastodon"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
)
var visibilitiesPrefStr = []string{
mastodon.VisibilityPublic,
mastodon.VisibilityUnlisted,
mastodon.VisibilityFollowersOnly,
}
type preferences struct {
displayname string
bio string
fields []mastodon.Field
visibility string
}
type PreferenceView struct {
tutView *TutView
shared *Shared
View *tview.Flex
displayName *tview.TextView
bio *tview.TextView
fields *tview.List
visibility *tview.DropDown
controls *tview.Flex
preferences *preferences
fieldFocus bool
}
func NewPreferenceView(tv *TutView) *PreferenceView {
p := &PreferenceView{
tutView: tv,
shared: tv.Shared,
displayName: NewTextView(tv.tut.Config),
bio: NewTextView(tv.tut.Config),
fields: NewList(tv.tut.Config),
visibility: NewDropDown(tv.tut.Config),
controls: NewControlView(tv.tut.Config),
preferences: &preferences{},
}
p.View = preferenceViewUI(p)
p.MainFocus()
p.Update()
return p
}
func preferenceViewUI(p *PreferenceView) *tview.Flex {
p.visibility.SetLabel("Default toot visibility: ")
p.visibility.SetOptions(visibilitiesPrefStr, p.visibilitySelected)
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.displayName, 1, 0, false).
AddItem(p.visibility, 2, 0, false).
AddItem(p.fields, 0, 1, false), 0, 1, false).
AddItem(tview.NewFlex().SetDirection(tview.FlexRow).
AddItem(p.bio, 0, 1, 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 *PreferenceView) Update() {
pf := &preferences{}
me := p.tutView.tut.Client.Me
pf.displayname = me.DisplayName
if me.Source != nil {
if me.Source.Note != nil {
pf.bio = *me.Source.Note
}
if me.Source.Fields != nil {
for _, f := range *me.Source.Fields {
pf.fields = append(pf.fields, mastodon.Field{
Name: f.Name,
Value: f.Value,
})
}
}
if me.Source.Privacy != nil {
pf.visibility = *me.Source.Privacy
}
}
p.preferences = pf
p.update()
}
func (p *PreferenceView) update() {
pf := p.preferences
p.displayName.SetText(fmt.Sprintf("Display name: %s", tview.Escape(pf.displayname)))
p.bio.SetText(fmt.Sprintf("Bio:\n%s", tview.Escape(pf.bio)))
p.fields.Clear()
for _, f := range pf.fields {
p.fields.AddItem(fmt.Sprintf("%s: %s\n", tview.Escape(f.Name), tview.Escape(f.Value)), "", 0, nil)
}
index := 0
for i, v := range visibilitiesPrefStr {
if pf.visibility == v {
index = i
break
}
}
p.visibility.SetCurrentOption(index)
}
func (p *PreferenceView) HasFieldFocus() bool {
return p.fieldFocus
}
func (p *PreferenceView) FieldFocus() {
p.fieldFocus = true
var items []Control
items = append(items, NewControl(p.tutView.tut.Config, p.tutView.tut.Config.Input.PreferenceFieldsAdd, true))
items = append(items, NewControl(p.tutView.tut.Config, p.tutView.tut.Config.Input.PreferenceFieldsEdit, true))
items = append(items, NewControl(p.tutView.tut.Config, p.tutView.tut.Config.Input.PreferenceFieldsDelete, true))
items = append(items, NewControl(p.tutView.tut.Config, p.tutView.tut.Config.Input.GlobalBack, 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)
}
}
cnf := p.tutView.tut.Config
p.fields.SetSelectedBackgroundColor(cnf.Style.ListSelectedBackground)
p.fields.SetSelectedTextColor(cnf.Style.ListSelectedText)
}
func (p *PreferenceView) MainFocus() {
p.fieldFocus = false
var items []Control
items = append(items, NewControl(p.tutView.tut.Config, p.tutView.tut.Config.Input.PreferenceName, true))
items = append(items, NewControl(p.tutView.tut.Config, p.tutView.tut.Config.Input.PreferenceVisibility, true))
items = append(items, NewControl(p.tutView.tut.Config, p.tutView.tut.Config.Input.PreferenceBio, true))
items = append(items, NewControl(p.tutView.tut.Config, p.tutView.tut.Config.Input.PreferenceFields, true))
items = append(items, NewControl(p.tutView.tut.Config, p.tutView.tut.Config.Input.PreferenceSave, 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)
}
}
cnf := p.tutView.tut.Config
p.fields.SetSelectedBackgroundColor(cnf.Style.Background)
p.fields.SetSelectedTextColor(cnf.Style.Text)
}
func (p *PreferenceView) PrevField() {
index := p.fields.GetCurrentItem()
if index-1 >= 0 {
p.fields.SetCurrentItem(index - 1)
}
}
func (p *PreferenceView) NextField() {
index := p.fields.GetCurrentItem()
if index+1 < p.fields.GetItemCount() {
p.fields.SetCurrentItem(index + 1)
}
}
func (p *PreferenceView) AddField() {
if p.fields.GetItemCount() > 3 {
p.tutView.ShowError("You can have a maximum of four fields.")
return
}
if p.tutView.tut.Config.General.UseInternalEditor {
p.tutView.EditorView.Init("name", 255, true, func(input string) {
p.addFieldOne(input, nil)
})
} else {
name, err := OpenEditorLengthLimit(p.tutView, "name", 255)
p.addFieldOne(name, err)
}
}
func (p *PreferenceView) addFieldOne(name string, err error) {
if err != nil {
p.tutView.ShowError(
fmt.Sprintf("Couldn't add name. Error: %v\n", err),
)
return
}
if len(name) == 0 {
p.tutView.ShowError("Name can't be empty.")
return
}
if p.tutView.tut.Config.General.UseInternalEditor {
p.tutView.EditorView.Init("value", 255, false, func(input string) {
p.addFieldTwo(name, input, nil)
})
} else {
value, err := OpenEditorLengthLimit(p.tutView, "value", 255)
p.addFieldTwo(name, value, err)
}
}
func (p *PreferenceView) addFieldTwo(name string, value string, err error) {
if err != nil {
p.tutView.ShowError(
fmt.Sprintf("Couldn't add value. Error: %v\n", err),
)
return
}
if len(value) == 0 {
p.tutView.ShowError("Value can't be empty.")
return
}
field := mastodon.Field{
Name: name,
Value: value,
}
p.preferences.fields = append(p.preferences.fields, field)
p.update()
p.fields.SetCurrentItem(p.fields.GetItemCount() - 1)
}
func (p *PreferenceView) EditField() {
if p.fields.GetItemCount() == 0 {
return
}
index := p.fields.GetCurrentItem()
if index < 0 || index >= len(p.preferences.fields) {
return
}
curr := p.preferences.fields[index]
if p.tutView.tut.Config.General.UseInternalEditor {
p.tutView.EditorView.Init(curr.Name, 255, true, func(input string) {
p.editFieldOne(index, input, curr.Value, nil)
})
} else {
name, err := OpenEditorLengthLimit(p.tutView, curr.Name, 255)
p.editFieldOne(index, name, curr.Value, err)
}
}
func (p *PreferenceView) editFieldOne(index int, name string, value string, err error) {
if err != nil {
p.tutView.ShowError(
fmt.Sprintf("Couldn't edit name. Error: %v\n", err),
)
return
}
if len(name) == 0 {
p.tutView.ShowError("Name can't be empty.")
return
}
if p.tutView.tut.Config.General.UseInternalEditor {
p.tutView.EditorView.Init(value, 255, false, func(input string) {
p.editFieldTwo(index, name, input, nil)
})
} else {
value, err := OpenEditorLengthLimit(p.tutView, value, 255)
p.editFieldTwo(index, name, value, err)
}
}
func (p *PreferenceView) editFieldTwo(index int, name string, value string, err error) {
if err != nil {
p.tutView.ShowError(
fmt.Sprintf("Couldn't edit value. Error: %v\n", err),
)
return
}
if len(value) == 0 {
p.tutView.ShowError("Value can't be empty.")
return
}
field := mastodon.Field{
Name: name,
Value: value,
}
p.preferences.fields[index] = field
p.update()
}
func (p *PreferenceView) DeleteField() {
if p.fields.GetItemCount() == 0 {
return
}
index := p.fields.GetCurrentItem()
if index < 0 || index >= len(p.preferences.fields) {
return
}
p.fields.RemoveItem(index)
p.preferences.fields = append(p.preferences.fields[:index], p.preferences.fields[index+1:]...)
p.update()
}
func (p *PreferenceView) EditBio() {
bio := p.preferences.bio
if p.tutView.tut.Config.General.UseInternalEditor {
p.tutView.EditorView.Init(bio, 500, true, func(input string) {
p.editBio(input, nil)
})
} else {
text, err := OpenEditorLengthLimit(p.tutView, bio, 500)
p.editBio(text, err)
}
}
func (p *PreferenceView) editBio(text string, err error) {
if err != nil {
p.tutView.ShowError(
fmt.Sprintf("Couldn't edit bio. Error: %v\n", err),
)
return
}
p.preferences.bio = text
p.update()
}
func (p *PreferenceView) EditDisplayname() {
dn := p.preferences.displayname
if p.tutView.tut.Config.General.UseInternalEditor {
p.tutView.EditorView.Init(dn, 30, true, func(input string) {
p.editDisplayname(input, nil)
})
} else {
text, err := OpenEditorLengthLimit(p.tutView, dn, 30)
p.editDisplayname(text, err)
}
}
func (p *PreferenceView) editDisplayname(text string, err error) {
if err != nil {
p.tutView.ShowError(
fmt.Sprintf("Couldn't edit display name. Error: %v\n", err),
)
return
}
p.preferences.displayname = text
p.update()
}
func (p *PreferenceView) visibilityInput(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.exitVisibility()
return nil
}
return event
}
func (p *PreferenceView) exitVisibility() {
p.tutView.tut.App.SetInputCapture(p.tutView.Input)
p.tutView.tut.App.SetFocus(p.tutView.View)
}
func (p *PreferenceView) visibilitySelected(s string, index int) {
_, p.preferences.visibility = p.visibility.GetCurrentOption()
p.exitVisibility()
}
func (p *PreferenceView) FocusVisibility() {
p.tutView.tut.App.SetInputCapture(p.visibilityInput)
p.tutView.tut.App.SetFocus(p.visibility)
ev := tcell.NewEventKey(tcell.KeyDown, 0, tcell.ModNone)
p.tutView.tut.App.QueueEvent(ev)
}
func (p *PreferenceView) Save() {
og := &preferences{}
me := p.tutView.tut.Client.Me
og.displayname = me.DisplayName
if me.Source != nil {
if me.Source.Note != nil {
og.bio = *me.Source.Note
}
if me.Source.Fields != nil {
for _, f := range *me.Source.Fields {
og.fields = append(og.fields, mastodon.Field{
Name: f.Name,
Value: f.Value,
})
}
}
if me.Source.Privacy != nil {
og.visibility = *me.Source.Privacy
}
}
profile := mastodon.Profile{
Source: &mastodon.AccountSource{},
}
if og.displayname != p.preferences.displayname {
profile.DisplayName = &p.preferences.displayname
}
if og.bio != p.preferences.bio {
profile.Note = &p.preferences.bio
}
if og.visibility != p.preferences.visibility {
profile.Source.Privacy = &p.preferences.visibility
}
profile.Fields = &p.preferences.fields
err := p.tutView.tut.Client.SavePreferences(&profile)
if err != nil {
p.tutView.ShowError(
fmt.Sprintf("Couldn't update preferences. Error: %v\n", err),
)
return
}
p.tutView.SetPage(MainFocus)
}