diff --git a/README.md b/README.md index 1bb43c4..37a103c 100644 --- a/README.md +++ b/README.md @@ -145,12 +145,14 @@ Flags: ``` ## Templates -You can customise how toots are displayed with a Go [text/template](https://pkg.go.dev/text/template). +You can customise how toots and user profiles are displayed with a +Go [text/template](https://pkg.go.dev/text/template). -You'll have to place a file named `toot.tmpl` in `XDG_CONFIG_HOME/tut/` which -usually equals to `~/.config/tut/`. +You'll have to place a file named `toot.tmpl` and/or `user.tmpl` +in `XDG_CONFIG_HOME/tut/` which usually equals to `~/.config/tut/`. -You can copy [toot.tmpl](./toot.tmpl) from this repo manually or with `curl` or `wget`. +You can copy [toot.tmpl](./toot.tmpl) and [user.tmpl](./user.tmpl) +from this repo manually or with `curl` or `wget`. ```bash cd ~/.config/tut @@ -158,14 +160,22 @@ cd ~/.config/tut # using curl curl -o toot.tmpl https://raw.githubusercontent.com/RasmusLindroth/tut/master/toot.tmpl +curl -o user.tmpl https://raw.githubusercontent.com/RasmusLindroth/tut/master/user.tmpl + # using wget wget https://raw.githubusercontent.com/RasmusLindroth/tut/master/toot.tmpl + +wget https://raw.githubusercontent.com/RasmusLindroth/tut/master/user.tmpl ``` -The data available for you is two structs. The first one is the `Toot`-struct, you can see all fields in [./feed.go](./feed.go). The second one is the `StyleConfig`-struct. You can find the fields in [./config.go](./config.go). +The data available for you in `toot.tmpl` is two structs. The first one is the `Toot`-struct, you can see all fields in [./feed.go](./feed.go). The second one is the `StyleConfig`-struct. You can find the fields in [./config.go](./config.go). You acces them with `.Toot` and `.Style` in your template file. +The data available in `user.tmpl` is almost the same. You still have the +`StyleConfig` but instead of `Toot` you have a struct named `User`. You can see +all fields in [./feed.go](./feed.go). + ## Password manager for secrets If you run `pass`, `gopass` or something similar you can protect your secrets. You'll have to manually update your `accounts.toml`. It should be located at diff --git a/api.go b/api.go index 17a5829..671079a 100644 --- a/api.go +++ b/api.go @@ -504,3 +504,7 @@ func (api *API) MuteUser(u mastodon.Account) (*mastodon.Relationship, error) { func (api *API) UnmuteUser(u mastodon.Account) (*mastodon.Relationship, error) { return api.Client.AccountUnmute(context.Background(), u.ID) } + +func (api *API) Vote(poll *mastodon.Poll, choices ...int) (*mastodon.Poll, error) { + return api.Client.PollVote(context.Background(), poll.ID, choices...) +} diff --git a/config.go b/config.go index 3940abc..ef57771 100644 --- a/config.go +++ b/config.go @@ -16,6 +16,9 @@ import ( //go:embed toot.tmpl var tootTemplate string +//go:embed user.tmpl +var userTemplate string + type Config struct { General GeneralConfig Style StyleConfig @@ -152,6 +155,7 @@ type NotificationConfig struct { type TemplatesConfig struct { TootTemplate *template.Template + UserTemplate *template.Template } func parseColor(input string, def string, xrdb map[string]string) tcell.Color { @@ -486,8 +490,31 @@ func ParseTemplates(cfg *ini.File) TemplatesConfig { if err != nil { log.Fatalf("Couldn't parse toot.tmpl. Error: %v", err) } + var userTmpl *template.Template + userTmplPath, exists, err := CheckConfig("user.tmpl") + if err != nil { + log.Fatalln( + fmt.Sprintf("Couldn't access user.tmpl. Error: %v", err), + ) + } + if exists { + userTmpl, err = template.New("user.tmpl").Funcs(template.FuncMap{ + "Color": ColorMark, + "Flags": TextFlags, + }).ParseFiles(userTmplPath) + } + if !exists || err != nil { + userTmpl, err = template.New("user.tmpl").Funcs(template.FuncMap{ + "Color": ColorMark, + "Flags": TextFlags, + }).Parse(userTemplate) + } + if err != nil { + log.Fatalf("Couldn't parse user.tmpl. Error: %v", err) + } return TemplatesConfig{ TootTemplate: tootTmpl, + UserTemplate: userTmpl, } } diff --git a/feed.go b/feed.go index 5ed08c6..f3c6523 100644 --- a/feed.go +++ b/feed.go @@ -30,6 +30,7 @@ type Feed interface { DrawList() DrawToot() DrawSpoiler() + RedrawPoll(*mastodon.Poll) RedrawControls() GetCurrentUser() *mastodon.Account GetCurrentStatus() *mastodon.Status @@ -109,8 +110,8 @@ func showTootOptions(app *App, status *mastodon.Status, showSensitive bool) (str Width: app.UI.StatusView.GetTextWidth(), ContentText: strippedContent, Boosted: status.Reblog != nil, - BoostedDisplayName: status.Account.DisplayName, - BoostedAcct: status.Account.Acct, + BoostedDisplayName: tview.Escape(status.Account.DisplayName), + BoostedAcct: tview.Escape(status.Account.Acct), ShowSpoiler: showSensitive, } @@ -118,13 +119,14 @@ func showTootOptions(app *App, status *mastodon.Status, showSensitive bool) (str status = status.Reblog } - toot.AccountDisplayName = status.Account.DisplayName - toot.Account = status.Account.Acct + toot.AccountDisplayName = tview.Escape(status.Account.DisplayName) + toot.Account = tview.Escape(status.Account.Acct) toot.Bookmarked = status.Bookmarked.(bool) toot.Visibility = status.Visibility toot.Spoiler = status.Sensitive if status.Poll != nil { + app.UI.VoteOverlay.SetPoll(status.Poll) p := *status.Poll toot.Poll = Poll{ ID: string(p.ID), @@ -239,30 +241,71 @@ func showTootOptions(app *App, status *mastodon.Status, showSensitive bool) (str return output.String(), controls } -func showUser(app *App, user *mastodon.Account, relation *mastodon.Relationship, showUserControl bool) (string, string) { - var text string - var controls string - - n := ColorMark(app.Config.Style.Text) - s1 := ColorMark(app.Config.Style.TextSpecial1) - s2 := ColorMark(app.Config.Style.TextSpecial2) +type User struct { + Username string + Account string + DisplayName string + Locked bool + CreatedAt time.Time + FollowersCount int64 + FollowingCount int64 + StatusCount int64 + Note string + URL string + Avatar string + AvatarStatic string + Header string + HeaderStatic string + Fields []Field + Bot bool + //Emojis []Emoji + //Moved *Account `json:"moved"` +} + +type Field struct { + Name string + Value string + VerifiedAt time.Time +} + +type DisplayUserData struct { + User User + Style StyleConfig +} - if user.DisplayName != "" { - text = fmt.Sprintf(s2+"%s\n", user.DisplayName) +func showUser(app *App, user *mastodon.Account, relation *mastodon.Relationship, showUserControl bool) (string, string) { + u := User{ + Username: tview.Escape(user.Username), + Account: tview.Escape(user.Acct), + DisplayName: tview.Escape(user.DisplayName), + Locked: user.Locked, + CreatedAt: user.CreatedAt, + FollowersCount: user.FollowersCount, + FollowingCount: user.FollowingCount, + StatusCount: user.StatusesCount, + URL: user.URL, + Avatar: user.Avatar, + AvatarStatic: user.AvatarStatic, + Header: user.Header, + HeaderStatic: user.HeaderStatic, + Bot: user.Bot, } - text += fmt.Sprintf(s1+"%s\n\n", user.Acct) - text += fmt.Sprintf("%sToots %s%d %sFollowers %s%d %sFollowing %s%d\n\n", - n, s2, user.StatusesCount, n, s2, user.FollowersCount, n, s2, user.FollowingCount) - - note, urls := cleanTootHTML(user.Note) - text += n + note + "\n\n" + var controls string + var urls []URL + fields := []Field{} + u.Note, urls = cleanTootHTML(user.Note) for _, f := range user.Fields { value, fu := cleanTootHTML(f.Value) - text += fmt.Sprintf("%s%s: %s%s\n", s2, f.Name, n, value) + fields = append(fields, Field{ + Name: tview.Escape(f.Name), + Value: tview.Escape(value), + VerifiedAt: f.VerifiedAt, + }) urls = append(urls, fu...) } + u.Fields = fields app.UI.LinkOverlay.SetLinks(urls, nil) @@ -294,7 +337,17 @@ func showUser(app *App, user *mastodon.Account, relation *mastodon.Relationship, controlItems = append(controlItems, ColorKey(app.Config, "", "Y", "ank")) controls = strings.Join(controlItems, " ") - return text, controls + ud := DisplayUserData{ + User: u, + Style: app.Config.Style, + } + var output bytes.Buffer + err := app.Config.Templates.UserTemplate.ExecuteTemplate(&output, "user.tmpl", ud) + if err != nil { + panic(err) + } + + return output.String(), controls } func drawStatusList(statuses []*mastodon.Status, longFormat, shortFormat string, relativeDate int) <-chan ListItem { @@ -348,6 +401,7 @@ const ( ControlReply ControlThread ControlUser + ControlVote ControlSpoiler ControlBookmark ControlYankStatus @@ -491,6 +545,10 @@ func inputSimple(app *App, event *tcell.EventKey, controls ControlItem, NewTimelineFeed(app, TimelineList, listInfo), ) } + case 'p', 'P': + if controls&ControlVote != 0 { + app.UI.ShowVote() + } case 'r', 'R': if controls&ControlReply != 0 { app.UI.Reply(status) @@ -696,6 +754,15 @@ func (t *TimelineFeed) GetSavedIndex() int { return t.index } +func (t *TimelineFeed) RedrawPoll(p *mastodon.Poll) { + s := t.GetCurrentStatus() + if s == nil { + return + } + s.Poll = p + t.DrawToot() +} + func (t *TimelineFeed) Input(event *tcell.EventKey) { status := t.GetCurrentStatus() originalStatus := status @@ -713,6 +780,11 @@ func (t *TimelineFeed) Input(event *tcell.EventKey) { ControlFavorite, ControlBoost, ControlDelete, ControlBookmark, ControlYankStatus, } + if status.Poll != nil { + if !status.Poll.Expired && !status.Poll.Voted { + controls = append(controls, ControlVote) + } + } options := inputOptions(controls) updated, rc, rt, newS, _ := inputSimple(t.app, event, options, user, status, originalStatus, nil, t, nil) @@ -821,6 +893,15 @@ func (t *ThreadFeed) GetSavedIndex() int { return t.index } +func (t *ThreadFeed) RedrawPoll(p *mastodon.Poll) { + s := t.GetCurrentStatus() + if s == nil { + return + } + s.Poll = p + t.DrawToot() +} + func (t *ThreadFeed) Input(event *tcell.EventKey) { status := t.GetCurrentStatus() originalStatus := status @@ -841,6 +922,11 @@ func (t *ThreadFeed) Input(event *tcell.EventKey) { if status.ID != t.status.ID { controls = append(controls, ControlThread) } + if status.Poll != nil { + if !status.Poll.Expired && !status.Poll.Voted { + controls = append(controls, ControlVote) + } + } options := inputOptions(controls) updated, rc, rt, newS, _ := inputSimple(t.app, event, options, user, status, originalStatus, nil, t, nil) @@ -1004,6 +1090,15 @@ func (u *UserFeed) GetSavedIndex() int { return u.index } +func (u *UserFeed) RedrawPoll(p *mastodon.Poll) { + s := u.GetCurrentStatus() + if s == nil { + return + } + s.Poll = p + u.DrawToot() +} + func (u *UserFeed) Input(event *tcell.EventKey) { index := u.GetSavedIndex() @@ -1037,6 +1132,11 @@ func (u *UserFeed) Input(event *tcell.EventKey) { ControlOpen, ControlReply, ControlMedia, ControlFavorite, ControlBoost, ControlDelete, ControlUser, ControlBookmark, ControlYankStatus, } + if status.Poll != nil { + if !status.Poll.Expired && !status.Poll.Voted { + controls = append(controls, ControlVote) + } + } options := inputOptions(controls) updated, rc, rt, newS, _ := inputSimple(u.app, event, options, user, status, originalStatus, nil, u, nil) @@ -1286,6 +1386,15 @@ func (n *NotificationsFeed) GetSavedIndex() int { return n.index } +func (n *NotificationsFeed) RedrawPoll(p *mastodon.Poll) { + s := n.GetCurrentStatus() + if s == nil { + return + } + s.Poll = p + n.DrawToot() +} + func (n *NotificationsFeed) Input(event *tcell.EventKey) { notification := n.GetCurrentNotification() if notification == nil { @@ -1327,6 +1436,11 @@ func (n *NotificationsFeed) Input(event *tcell.EventKey) { ControlFavorite, ControlBoost, ControlDelete, ControlBookmark, ControlYankStatus, } + if status.Poll != nil { + if !status.Poll.Expired && !status.Poll.Voted { + controls = append(controls, ControlVote) + } + } options := inputOptions(controls) updated, rc, rt, newS, _ := inputSimple(n.app, event, options, notification.N.Account, status, originalStatus, nil, n, nil) @@ -1463,6 +1577,15 @@ func (t *TagFeed) GetSavedIndex() int { return t.index } +func (t *TagFeed) RedrawPoll(p *mastodon.Poll) { + s := t.GetCurrentStatus() + if s == nil { + return + } + s.Poll = p + t.DrawToot() +} + func (t *TagFeed) Input(event *tcell.EventKey) { status := t.GetCurrentStatus() originalStatus := status @@ -1480,6 +1603,11 @@ func (t *TagFeed) Input(event *tcell.EventKey) { ControlFavorite, ControlBoost, ControlDelete, ControlBookmark, ControlYankStatus, } + if status.Poll != nil { + if !status.Poll.Expired && !status.Poll.Voted { + controls = append(controls, ControlVote) + } + } options := inputOptions(controls) updated, rc, rt, newS, _ := inputSimple(t.app, event, options, user, status, originalStatus, nil, t, nil) @@ -1651,6 +1779,9 @@ func (u *UserListFeed) GetSavedIndex() int { return u.index } +func (u *UserListFeed) RedrawPoll(p *mastodon.Poll) { +} + func (u *UserListFeed) Input(event *tcell.EventKey) { index := u.GetSavedIndex() if index > len(u.users)-1 || len(u.users) == 0 { @@ -1760,6 +1891,10 @@ func (l *ListFeed) DrawToot() { func (l *ListFeed) GetSavedIndex() int { return l.index + +} + +func (t *ListFeed) RedrawPoll(p *mastodon.Poll) { } func (l *ListFeed) Input(event *tcell.EventKey) { diff --git a/go.mod b/go.mod index d01f073..0665b0f 100644 --- a/go.mod +++ b/go.mod @@ -9,15 +9,13 @@ require ( github.com/gobwas/glob v0.2.3 github.com/godbus/dbus/v5 v5.0.6 // indirect github.com/gopherjs/gopherjs v0.0.0-20211101210129-f9bde24e5ca2 // indirect - github.com/gorilla/websocket v1.4.2 // indirect github.com/icza/gox v0.0.0-20210726201659-cd40a3f8d324 - github.com/mattn/go-mastodon v0.0.5-0.20210629151305-d39c10ba5e94 + github.com/mattn/go-mastodon v0.0.5-0.20211104150201-58c389181352 github.com/microcosm-cc/bluemonday v1.0.16 github.com/pelletier/go-toml/v2 v2.0.0-beta.4 github.com/rivo/tview v0.0.0-20211029142923-a4acb08f513e github.com/rivo/uniseg v0.2.0 golang.org/x/net v0.0.0-20211101193420-4a448f8816b3 - golang.org/x/sys v0.0.0-20211102061401-a2f17f7b995c // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect gopkg.in/ini.v1 v1.63.2 diff --git a/go.sum b/go.sum index 3e5a938..336b556 100644 --- a/go.sum +++ b/go.sum @@ -39,8 +39,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg= -github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= +github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI= +github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -61,7 +61,9 @@ github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnht github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -73,7 +75,7 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= @@ -164,7 +166,6 @@ github.com/gopherjs/gopherwasm v1.1.0 h1:fA2uLoctU5+T3OhOn2vYP0DVT6pxc7xhTlBB1pa github.com/gopherjs/gopherwasm v1.1.0/go.mod h1:SkZ8z7CWBz5VXbhJel8TxCmAcsQqzgWGR/8nMhyhZSI= github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= @@ -208,12 +209,15 @@ github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-mastodon v0.0.5-0.20210629151305-d39c10ba5e94 h1:77aS7G4ljsC/dLfOeu5HcSdShyR+bZzyTO8CC+uFu7Q= -github.com/mattn/go-mastodon v0.0.5-0.20210629151305-d39c10ba5e94/go.mod h1:CZ3bPYRNGgvMZr4d/SNMvCObyCQvTgCXdIOrW040z5U= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-mastodon v0.0.5-0.20211104150201-58c389181352 h1:zxF8a6o96VQe9ZV5gMfdhw/2Mo744rCIM0SprndUyAw= +github.com/mattn/go-mastodon v0.0.5-0.20211104150201-58c389181352/go.mod h1:D8ScK24P+nSB6g5xdsi/m40TIWispU4yyhJw9rGgHx4= github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= @@ -254,6 +258,7 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= @@ -282,7 +287,7 @@ github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af h1:6yITBqGTE2lEeTPG0 github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af/go.mod h1:4F09kP5F+am0jAwlQLddpoMDM+iewkxxt6nxUQ5nq5o= github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 h1:nrZ3ySNYwJbSpD6ce9duiP+QkD3JuLCcWkdaehUS/3Y= github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80/go.mod h1:iFyPdL66DjUD96XmzVL3ZntbzcflLnznH0fr99w5VqE= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -344,11 +349,9 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -383,6 +386,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211101193420-4a448f8816b3 h1:VrJZAjbekhoRn7n5FBujY31gboH+iB3pdLxn3gE9FjU= golang.org/x/net v0.0.0-20211101193420-4a448f8816b3/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -423,11 +427,11 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -457,8 +461,9 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211102061401-a2f17f7b995c h1:QOfDMdrf/UwlVR0UBq2Mpr58UzNtvgJRXA4BgPfFACs= -golang.org/x/sys v0.0.0-20211102061401-a2f17f7b995c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211103235746-7861aae1554b h1:1VkfZQv42XQlA/jchYumAnv1UPo6RgF9rJFkTgZIxO4= +golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/images/preview.png b/images/preview.png index 7aad749..e49dfdb 100644 Binary files a/images/preview.png and b/images/preview.png differ diff --git a/main.go b/main.go index 0769ffa..c170b92 100644 --- a/main.go +++ b/main.go @@ -9,7 +9,7 @@ import ( "github.com/gdamore/tcell/v2" ) -const version string = "0.0.37" +const version string = "0.0.38" func main() { newUser := false @@ -151,10 +151,6 @@ func main() { app.UI.UserSelectOverlay.InputHandler(event) return nil } else { - if event.Key() == tcell.KeyRune { - switch event.Rune() { - } - } return event } } @@ -169,6 +165,11 @@ func main() { return nil } + if app.UI.Focus == VoteOverlayFocus { + app.UI.VoteOverlay.InputHandler(event) + return nil + } + if app.UI.Focus == CmdBarFocus { switch event.Key() { case tcell.KeyEnter: @@ -206,7 +207,11 @@ func main() { app.UI.SetFocus(VisibilityOverlayFocus) return nil case 'q', 'Q': - app.UI.SetFocus(LeftPaneFocus) + if app.UI.StatusView.lastList == NotificationPaneFocus { + app.UI.SetFocus(NotificationPaneFocus) + } else { + app.UI.SetFocus(LeftPaneFocus) + } return nil } } else { diff --git a/messagebox.go b/messagebox.go index 4754bd7..81fa4a4 100644 --- a/messagebox.go +++ b/messagebox.go @@ -159,6 +159,11 @@ func (m *MessageBox) Post() { m.app.UI.CmdBar.ShowError(fmt.Sprintf("Couldn't post toot. Error: %v\n", err)) return } + if m.app.UI.StatusView.lastList == NotificationPaneFocus { + m.app.UI.SetFocus(NotificationPaneFocus) + } else { + m.app.UI.SetFocus(LeftPaneFocus) + } m.app.UI.SetFocus(LeftPaneFocus) } diff --git a/statusview.go b/statusview.go index dc54b74..870f2e6 100644 --- a/statusview.go +++ b/statusview.go @@ -227,6 +227,13 @@ func (t *StatusView) GetTextWidth() int { return width } +func (t *StatusView) RedrawPoll(p *mastodon.Poll) { + if len(t.feeds) == 0 { + return + } + t.feeds[t.feedIndex].RedrawPoll(p) +} + func (t *StatusView) GetCurrentItem() int { return t.list.GetCurrentItem() } diff --git a/toot.tmpl b/toot.tmpl index 37ececf..0e3613a 100644 --- a/toot.tmpl +++ b/toot.tmpl @@ -28,11 +28,21 @@ {{- if or (not .Toot.Spoiler) (.Toot.ShowSpoiler) -}} {{ Color .Style.Text }}{{ .Toot.ContentText }} {{ if ne .Toot.Poll.ID "" }} -{{ Color .Style.Subtle }}{{ Flags "b" }}Poll{{ Flags "-" }} +{{ if .Toot.Poll.Voted -}} +{{- Color .Style.Subtle }}{{ Flags "b" }}Poll - you have voted{{ Flags "-" -}} +{{ else if not .Toot.Poll.Expired }} +{{- Color .Style.Subtle }}{{ Flags "b" }}Poll - press [p[] to vote{{ Flags "-" -}} +{{ else }} +{{- Color .Style.Subtle }}{{ Flags "b" }}Poll - expired {{ Flags "-" -}} +{{ end }} {{ Color .Style.Text }}Number of votes: {{ .Toot.Poll.VotesCount }} {{ range .Toot.Poll.Options }} +{{- if or ($.Toot.Poll.Voted) ($.Toot.Poll.Expired) -}} {{- .Title }} - {{ .Percent }}% ({{ .VotesCount }}) +{{- else -}} +{{- .Title -}} +{{ end }} {{ end -}} {{ end -}} {{ range .Toot.Media }} diff --git a/ui.go b/ui.go index 972f05a..c49e3e1 100644 --- a/ui.go +++ b/ui.go @@ -21,6 +21,7 @@ const ( MessageAttachmentFocus LinkOverlayFocus VisibilityOverlayFocus + VoteOverlayFocus AuthOverlayFocus UserSelectFocus ) @@ -56,6 +57,7 @@ func (ui *UI) Init() { ui.MessageBox = NewMessageBox(ui.app) ui.LinkOverlay = NewLinkOverlay(ui.app) ui.VisibilityOverlay = NewVisibilityOverlay(ui.app) + ui.VoteOverlay = NewVoteOverlay(ui.app) ui.AuthOverlay = NewAuthOverlay(ui.app) ui.UserSelectOverlay = NewUserSelectOverlay(ui.app) ui.MediaOverlay = NewMediaOverlay(ui.app) @@ -112,6 +114,15 @@ func (ui *UI) Init() { AddItem(ui.VisibilityOverlay.TextBottom, 1, 1, true), 0, 8, false). AddItem(nil, 0, 1, false), 0, 8, true). AddItem(nil, 0, 1, false), true, false) + ui.Pages.AddPage("vote", tview.NewFlex().AddItem(nil, 0, 1, false). + AddItem(tview.NewFlex().SetDirection(tview.FlexRow). + AddItem(nil, 0, 1, false). + AddItem(ui.VoteOverlay.Flex.SetDirection(tview.FlexRow). + AddItem(ui.VoteOverlay.TextTop, 3, 1, true). + AddItem(ui.VoteOverlay.List, 0, 10, true). + AddItem(ui.VoteOverlay.TextBottom, 1, 1, true), 0, 8, false). + AddItem(nil, 0, 1, false), 0, 8, true). + AddItem(nil, 0, 1, false), true, false) ui.Pages.AddPage("login", tview.NewFlex(). AddItem(nil, 0, 1, false). @@ -162,6 +173,7 @@ type UI struct { Pages *tview.Pages LinkOverlay *LinkOverlay VisibilityOverlay *VisibilityOverlay + VoteOverlay *VoteOverlay AuthOverlay *AuthOverlay UserSelectOverlay *UserSelectOverlay MediaOverlay *MediaView @@ -200,6 +212,10 @@ func (ui *UI) SetFocus(f FocusAt) { ui.Pages.ShowPage("links") ui.Root.SetFocus(ui.LinkOverlay.List) ui.FocusAt(ui.LinkOverlay.List, "-- LINK --") + case VoteOverlayFocus: + ui.Pages.ShowPage("vote") + ui.Root.SetFocus(ui.VoteOverlay.List) + ui.FocusAt(ui.VoteOverlay.List, "-- VOTE --") case VisibilityOverlayFocus: ui.VisibilityOverlay.Show() ui.Pages.ShowPage("visibility") @@ -303,6 +319,10 @@ func (ui *UI) ShowLinks() { ui.SetFocus(LinkOverlayFocus) } +func (ui *UI) ShowVote() { + ui.SetFocus(VoteOverlayFocus) +} + func (ui *UI) OpenMedia(status *mastodon.Status) { if status.Reblog != nil { status = status.Reblog diff --git a/user.tmpl b/user.tmpl new file mode 100644 index 0000000..1c25324 --- /dev/null +++ b/user.tmpl @@ -0,0 +1,18 @@ +{{- if .User.Bot -}} +{{ Color .Style.Subtle }}The user is a bot +{{ end -}} +{{- if ne .User.DisplayName "" -}} +{{- Color .Style.TextSpecial2 }}{{ .User.DisplayName }} +{{ Color .Style.TextSpecial1 }}{{ .User.Account }} +{{- else -}} +{{ Color .Style.TextSpecial2 }}{{- .User.Account }} +{{ end }} + +{{ Color .Style.Text }}Toots {{ Color .Style.TextSpecial2 }}{{ .User.StatusCount -}} +{{- Color .Style.Text }} Followers {{ Color .Style.TextSpecial2 }}{{ .User.FollowersCount -}} +{{- Color .Style.Text }} Following {{ Color .Style.TextSpecial2 }}{{ .User.FollowingCount }} + +{{ Color .Style.Text }}{{ .User.Note }} +{{ range .User.Fields }} +{{ Color $.Style.TextSpecial2 }}{{ .Name }}:{{ Color $.Style.Text }} {{ .Value -}} +{{ end }} diff --git a/voteoverlay.go b/voteoverlay.go new file mode 100644 index 0000000..b2571c6 --- /dev/null +++ b/voteoverlay.go @@ -0,0 +1,185 @@ +package main + +import ( + "fmt" + "strings" + + "github.com/gdamore/tcell/v2" + "github.com/mattn/go-mastodon" + "github.com/rivo/tview" +) + +func NewVoteOverlay(app *App) *VoteOverlay { + v := &VoteOverlay{ + app: app, + Flex: tview.NewFlex(), + TextTop: tview.NewTextView(), + TextBottom: tview.NewTextView(), + List: tview.NewList(), + } + + v.TextTop.SetBackgroundColor(app.Config.Style.Background) + v.TextTop.SetTextColor(app.Config.Style.Text) + v.TextTop.SetDynamicColors(true) + v.TextBottom.SetBackgroundColor(app.Config.Style.Background) + v.TextBottom.SetDynamicColors(true) + v.List.SetBackgroundColor(app.Config.Style.Background) + v.List.SetMainTextColor(app.Config.Style.Text) + v.List.SetSelectedBackgroundColor(app.Config.Style.ListSelectedBackground) + v.List.SetSelectedTextColor(app.Config.Style.ListSelectedText) + v.List.ShowSecondaryText(false) + v.List.SetHighlightFullLine(true) + v.Flex.SetDrawFunc(app.Config.ClearContent) + var items []string + items = append(items, ColorKey(app.Config, "Select ", "Space/Enter", "")) + items = append(items, ColorKey(app.Config, "", "V", "ote")) + v.TextBottom.SetText(strings.Join(items, " ")) + return v +} + +type VoteOverlay struct { + app *App + Flex *tview.Flex + TextTop *tview.TextView + TextBottom *tview.TextView + List *tview.List + poll *mastodon.Poll + selected []int +} + +func (v *VoteOverlay) SetPoll(poll *mastodon.Poll) { + v.poll = poll + v.selected = []int{} + v.List.Clear() + if v.poll.Multiple { + v.TextTop.SetText( + tview.Escape("You can select multiple options. Press [v] to vote when you're finished selecting"), + ) + } else { + v.TextTop.SetText( + tview.Escape("You can only select ONE option. Press [v] to vote when you're finished selecting"), + ) + } + for _, o := range poll.Options { + v.List.AddItem(tview.Escape(o.Title), "", 0, nil) + } +} + +func (v *VoteOverlay) Prev() { + index := v.List.GetCurrentItem() + if index-1 >= 0 { + v.List.SetCurrentItem(index - 1) + } +} + +func (v *VoteOverlay) Next() { + index := v.List.GetCurrentItem() + if index+1 < v.List.GetItemCount() { + v.List.SetCurrentItem(index + 1) + } +} + +func (v *VoteOverlay) ToggleSelect() { + index := v.List.GetCurrentItem() + inSelected := false + for _, value := range v.selected { + if index == value { + inSelected = true + break + } + } + if inSelected { + v.Unselect() + } else { + v.Select() + } +} + +func (v *VoteOverlay) Select() { + if !v.poll.Multiple && len(v.selected) > 0 { + return + } + index := v.List.GetCurrentItem() + inSelected := false + for _, value := range v.selected { + if index == value { + inSelected = true + break + } + } + if inSelected { + return + } + v.selected = append(v.selected, index) + v.List.SetItemText(index, + tview.Escape(fmt.Sprintf("[x] %s", v.poll.Options[index].Title)), + "") +} + +func (v *VoteOverlay) Unselect() { + index := v.List.GetCurrentItem() + sel := []int{} + for _, value := range v.selected { + if value == index { + continue + } + sel = append(sel, value) + } + v.selected = sel + v.List.SetItemText(index, + tview.Escape(v.poll.Options[index].Title), + "") +} + +func (v *VoteOverlay) Vote() { + if len(v.selected) == 0 { + return + } + p, err := v.app.API.Vote(v.poll, v.selected...) + if err != nil { + v.app.UI.CmdBar.ShowError(fmt.Sprintf("Couldn't vote. Error: %v\n", err)) + return + } + v.app.UI.StatusView.RedrawPoll(p) + if v.app.UI.StatusView.lastList == NotificationPaneFocus { + v.app.UI.SetFocus(NotificationPaneFocus) + } else { + v.app.UI.SetFocus(LeftPaneFocus) + } +} + +func (v *VoteOverlay) InputHandler(event *tcell.EventKey) { + if event.Key() == tcell.KeyRune { + switch event.Rune() { + case 'j', 'J': + v.Next() + case 'k', 'K': + v.Prev() + case 'v', 'V': + v.Vote() + case ' ': + v.ToggleSelect() + case 'q', 'Q': + if v.app.UI.StatusView.lastList == NotificationPaneFocus { + v.app.UI.SetFocus(NotificationPaneFocus) + } else { + v.app.UI.SetFocus(LeftPaneFocus) + } + } + } else { + switch event.Key() { + case tcell.KeyEnter: + v.ToggleSelect() + case tcell.KeyUp: + v.Prev() + case tcell.KeyDown: + v.Next() + case tcell.KeyEsc: + if v.app.UI.StatusView.lastList == NotificationPaneFocus { + v.app.UI.SetFocus(NotificationPaneFocus) + } else { + v.app.UI.SetFocus(LeftPaneFocus) + } + } + } +}