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.

219 lines
4.9 KiB

package main
import (
"fmt"
"strconv"
"strings"
"github.com/gdamore/tcell/v2"
"github.com/mattn/go-mastodon"
"github.com/rivo/tview"
)
func NewLinkOverlay(app *App) *LinkOverlay {
l := &LinkOverlay{
app: app,
Flex: tview.NewFlex(),
TextBottom: tview.NewTextView(),
List: tview.NewList(),
}
l.TextBottom.SetBackgroundColor(app.Config.Style.Background)
l.TextBottom.SetDynamicColors(true)
l.List.SetBackgroundColor(app.Config.Style.Background)
l.List.SetMainTextColor(app.Config.Style.Text)
l.List.SetSelectedBackgroundColor(app.Config.Style.ListSelectedBackground)
l.List.SetSelectedTextColor(app.Config.Style.ListSelectedText)
l.List.ShowSecondaryText(false)
l.List.SetHighlightFullLine(true)
l.Flex.SetDrawFunc(app.Config.ClearContent)
var items []string
items = append(items, ColorKey(app.Config, "", "O", "pen"))
items = append(items, ColorKey(app.Config, "", "Y", "ank"))
for _, cust := range app.Config.OpenCustom.OpenCustoms {
items = append(items, ColorKey(app.Config, "", fmt.Sprintf("%d", cust.Index), cust.Name))
}
l.TextBottom.SetText(strings.Join(items, " "))
return l
}
type LinkOverlay struct {
app *App
Flex *tview.Flex
TextBottom *tview.TextView
List *tview.List
urls []URL
mentions []mastodon.Mention
tags []mastodon.Tag
}
func (l *LinkOverlay) SetLinks(urls []URL, status *mastodon.Status) {
realUrls := []URL{}
l.urls = []URL{}
l.mentions = []mastodon.Mention{}
l.tags = []mastodon.Tag{}
if urls != nil {
if status != nil {
for _, url := range urls {
isNotMention := true
for _, mention := range status.Mentions {
if mention.URL == url.URL {
isNotMention = false
}
}
if isNotMention {
realUrls = append(realUrls, url)
}
}
} else {
realUrls = urls
}
l.urls = realUrls
}
if status != nil {
l.mentions = status.Mentions
l.tags = status.Tags
}
l.List.Clear()
for _, url := range realUrls {
l.List.AddItem(url.Text, "", 0, nil)
}
for _, mention := range l.mentions {
l.List.AddItem(mention.Acct, "", 0, nil)
}
for _, tag := range l.tags {
l.List.AddItem("#"+tag.Name, "", 0, nil)
}
}
func (l *LinkOverlay) Prev() {
index := l.List.GetCurrentItem()
if index-1 >= 0 {
l.List.SetCurrentItem(index - 1)
}
}
func (l *LinkOverlay) Next() {
index := l.List.GetCurrentItem()
if index+1 < l.List.GetItemCount() {
l.List.SetCurrentItem(index + 1)
}
}
func (l *LinkOverlay) Open() {
index := l.List.GetCurrentItem()
total := len(l.urls) + len(l.mentions) + len(l.tags)
if total == 0 || index >= total {
return
}
if index < len(l.urls) {
openURL(l.app.UI.Root, l.app.Config.Media, l.app.Config.OpenPattern, l.urls[index].URL)
return
}
mIndex := index - len(l.urls)
if mIndex < len(l.mentions) {
u, err := l.app.API.GetUserByID(l.mentions[mIndex].ID)
if err != nil {
l.app.UI.CmdBar.ShowError(fmt.Sprintf("Couldn't load user. Error: %v\n", err))
return
}
l.app.UI.StatusView.AddFeed(
NewUserFeed(l.app, *u),
)
l.app.UI.SetFocus(LeftPaneFocus)
return
}
tIndex := index - len(l.mentions) - len(l.urls)
if tIndex < len(l.tags) {
l.app.UI.StatusView.AddFeed(
NewTagFeed(l.app, l.tags[tIndex].Name),
)
l.app.UI.SetFocus(LeftPaneFocus)
}
}
func (l *LinkOverlay) CopyToClipboard() {
text := l.GetURL()
if text != "" {
e := copyToClipboard(text)
if !e {
l.app.UI.CmdBar.ShowError("Couldn't copy to clipboard.")
}
}
}
func (l *LinkOverlay) GetURL() string {
index := l.List.GetCurrentItem()
total := len(l.urls) + len(l.mentions) + len(l.tags)
if total == 0 || index >= total {
return ""
}
if index < len(l.urls) {
return l.urls[index].URL
}
mIndex := index - len(l.urls)
if mIndex < len(l.mentions) {
return l.mentions[mIndex].URL
}
tIndex := index - len(l.mentions) - len(l.urls)
if tIndex < len(l.tags) {
return l.tags[tIndex].URL
}
return ""
}
func (l *LinkOverlay) OpenCustom(index int) {
url := l.GetURL()
customs := l.app.Config.OpenCustom.OpenCustoms
for _, c := range customs {
if c.Index != index {
continue
}
openCustom(l.app.UI.Root, c.Program, c.Args, c.Terminal, url)
return
}
}
func (l *LinkOverlay) InputHandler(event *tcell.EventKey) {
if event.Key() == tcell.KeyRune {
switch event.Rune() {
case 'j', 'J':
l.Next()
case 'k', 'K':
l.Prev()
case 'o', 'O':
l.Open()
case 'y', 'Y':
l.CopyToClipboard()
case '1', '2', '3', '4', '5':
s := string(event.Rune())
i, _ := strconv.Atoi(s)
l.OpenCustom(i)
case 'q', 'Q':
if l.app.UI.StatusView.lastList == NotificationPaneFocus {
l.app.UI.SetFocus(NotificationPaneFocus)
} else {
l.app.UI.SetFocus(LeftPaneFocus)
}
}
} else {
switch event.Key() {
case tcell.KeyEnter:
l.Open()
case tcell.KeyUp:
l.Prev()
case tcell.KeyDown:
l.Next()
case tcell.KeyEsc:
if l.app.UI.StatusView.lastList == NotificationPaneFocus {
l.app.UI.SetFocus(NotificationPaneFocus)
} else {
l.app.UI.SetFocus(LeftPaneFocus)
}
}
}
}