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.
226 lines
4.9 KiB
226 lines
4.9 KiB
package ui |
|
|
|
import ( |
|
"context" |
|
"fmt" |
|
"log" |
|
"os" |
|
"strings" |
|
"time" |
|
|
|
"github.com/RasmusLindroth/go-mastodon" |
|
"github.com/RasmusLindroth/tut/api" |
|
"github.com/RasmusLindroth/tut/auth" |
|
"github.com/RasmusLindroth/tut/config" |
|
"github.com/rivo/tview" |
|
) |
|
|
|
type TimelineFocusAt uint |
|
|
|
const ( |
|
FeedFocus TimelineFocusAt = iota |
|
NotificationFocus |
|
) |
|
|
|
type SubFocusAt uint |
|
|
|
const ( |
|
ListFocus SubFocusAt = iota |
|
ContentFocus |
|
) |
|
|
|
type Tut struct { |
|
Client *api.AccountClient |
|
App *tview.Application |
|
Config *config.Config |
|
} |
|
|
|
type TutView struct { |
|
tut *Tut |
|
Timeline *Timeline |
|
PageFocus PageFocusAt |
|
PrevPageFocus PageFocusAt |
|
SubFocus SubFocusAt |
|
Leader *Leader |
|
Shared *Shared |
|
View *tview.Pages |
|
|
|
LoginView *LoginView |
|
MainView *MainView |
|
LinkView *LinkView |
|
ComposeView *ComposeView |
|
VoteView *VoteView |
|
PollView *PollView |
|
PreferenceView *PreferenceView |
|
HelpView *HelpView |
|
ModalView *ModalView |
|
|
|
FileList []string |
|
} |
|
|
|
func (tv *TutView) CleanExit(code int) { |
|
for _, f := range tv.FileList { |
|
os.Remove(f) |
|
} |
|
os.Exit(code) |
|
} |
|
|
|
func NewLeader(tv *TutView) *Leader { |
|
return &Leader{ |
|
tv: tv, |
|
} |
|
} |
|
|
|
type Leader struct { |
|
tv *TutView |
|
timeStart time.Time |
|
content string |
|
} |
|
|
|
func (l *Leader) IsActive() bool { |
|
td := time.Duration(l.tv.tut.Config.General.LeaderTimeout) |
|
return time.Since(l.timeStart) < td*time.Millisecond |
|
} |
|
|
|
func (l *Leader) Reset() { |
|
l.timeStart = time.Now() |
|
l.content = "" |
|
} |
|
|
|
func (l *Leader) ResetInactive() { |
|
l.timeStart = time.Now().Add(-1 * time.Hour) |
|
l.content = "" |
|
} |
|
|
|
func (l *Leader) AddRune(r rune) { |
|
l.content += string(r) |
|
} |
|
|
|
func (l *Leader) Content() string { |
|
return l.content |
|
} |
|
|
|
func NewTutView(t *Tut, accs *auth.AccountData, selectedUser string) *TutView { |
|
tv := &TutView{ |
|
tut: t, |
|
View: tview.NewPages(), |
|
FileList: []string{}, |
|
} |
|
tv.Leader = NewLeader(tv) |
|
tv.Shared = NewShared(tv) |
|
if selectedUser != "" { |
|
useHost := false |
|
found := false |
|
if strings.Contains(selectedUser, "@") { |
|
useHost = true |
|
} |
|
for _, acc := range accs.Accounts { |
|
accName := acc.Name |
|
if useHost { |
|
host := strings.TrimPrefix(acc.Server, "https://") |
|
host = strings.TrimPrefix(host, "http://") |
|
accName += "@" + host |
|
} |
|
if accName == selectedUser { |
|
tv.loggedIn(acc) |
|
found = true |
|
break |
|
} |
|
} |
|
if !found { |
|
log.Fatalf("Couldn't find a user named %s. Try again", selectedUser) |
|
} |
|
} else if len(accs.Accounts) > 1 { |
|
tv.LoginView = NewLoginView(tv, accs) |
|
tv.View.AddPage("login", tv.LoginView.View, true, true) |
|
tv.SetPage(LoginFocus) |
|
} else { |
|
tv.loggedIn(accs.Accounts[0]) |
|
} |
|
return tv |
|
} |
|
|
|
func (tv *TutView) loggedIn(acc auth.Account) { |
|
conf := &mastodon.Config{ |
|
Server: acc.Server, |
|
ClientID: acc.ClientID, |
|
ClientSecret: acc.ClientSecret, |
|
AccessToken: acc.AccessToken, |
|
} |
|
if tv.tut.Config.General.ShowHelp { |
|
tv.Shared.Bottom.Cmd.ShowMsg("Press ? or :help to learn how tut functions") |
|
} |
|
client := mastodon.NewClient(conf) |
|
me, err := client.GetAccountCurrentUser(context.Background()) |
|
if err != nil { |
|
fmt.Printf("Couldn't login. Error %s\n", err) |
|
tv.tut.App.Stop() |
|
tv.CleanExit(1) |
|
} |
|
filters, _ := client.GetFilters(context.Background()) |
|
ac := &api.AccountClient{ |
|
Me: me, |
|
Client: client, |
|
Streams: make(map[string]*api.Stream), |
|
Filters: filters, |
|
} |
|
tv.tut.Client = ac |
|
|
|
update := make(chan bool, 1) |
|
tv.SubFocus = ListFocus |
|
tv.LinkView = NewLinkView(tv) |
|
tv.Timeline = NewTimeline(tv, update) |
|
tv.MainView = NewMainView(tv, update) |
|
tv.ComposeView = NewComposeView(tv) |
|
tv.VoteView = NewVoteView(tv) |
|
tv.PollView = NewPollView(tv) |
|
tv.PreferenceView = NewPreferenceView(tv) |
|
tv.HelpView = NewHelpView(tv) |
|
tv.ModalView = NewModalView(tv) |
|
|
|
tv.View.AddPage("main", tv.MainView.View, true, false) |
|
tv.View.AddPage("link", tv.LinkView.View, true, false) |
|
tv.View.AddPage("compose", tv.ComposeView.View, true, false) |
|
tv.View.AddPage("vote", tv.VoteView.View, true, false) |
|
tv.View.AddPage("help", tv.HelpView.View, true, false) |
|
tv.View.AddPage("poll", tv.PollView.View, true, false) |
|
tv.View.AddPage("preference", tv.PreferenceView.View, true, false) |
|
tv.View.AddPage("modal", tv.ModalView.View, true, false) |
|
tv.SetPage(MainFocus) |
|
} |
|
|
|
func (tv *TutView) FocusFeed(index int) { |
|
if index < 0 || index >= len(tv.Timeline.Feeds) { |
|
return |
|
} |
|
tv.Timeline.FeedFocusIndex = index |
|
for i := 0; i < len(tv.Timeline.Feeds); i++ { |
|
if i == index { |
|
for _, f := range tv.Timeline.Feeds[i].Feeds { |
|
f.ListInFocus() |
|
} |
|
} else { |
|
for _, f := range tv.Timeline.Feeds[i].Feeds { |
|
f.ListOutFocus() |
|
} |
|
} |
|
} |
|
tv.Shared.Top.SetText(tv.Timeline.GetTitle()) |
|
tv.Timeline.update <- true |
|
} |
|
|
|
func (tv *TutView) NextFeed() { |
|
index := tv.Timeline.FeedFocusIndex + 1 |
|
if index >= len(tv.Timeline.Feeds) { |
|
index = 0 |
|
} |
|
tv.FocusFeed(index) |
|
} |
|
|
|
func (tv *TutView) PrevFeed() { |
|
index := tv.Timeline.FeedFocusIndex - 1 |
|
if index < 0 { |
|
index = len(tv.Timeline.Feeds) - 1 |
|
} |
|
tv.FocusFeed(index) |
|
}
|
|
|