Browse Source

38 (#103)

* template support for profiles

* update version

* show that a user is a bot

* Add support for voting on polls

* Update screenshot
pull/106/head 0.0.38
Rasmus Lindroth 4 years ago committed by GitHub
parent
commit
5baf927871
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 20
      README.md
  2. 4
      api.go
  3. 27
      config.go
  4. 177
      feed.go
  5. 4
      go.mod
  6. 31
      go.sum
  7. BIN
      images/preview.png
  8. 17
      main.go
  9. 5
      messagebox.go
  10. 7
      statusview.go
  11. 12
      toot.tmpl
  12. 20
      ui.go
  13. 18
      user.tmpl
  14. 185
      voteoverlay.go

20
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

4
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...)
}

27
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,
}
}

177
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) {

4
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

31
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=

BIN
images/preview.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 59 KiB

17
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 {

5
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)
}

7
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()
}

12
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 }}

20
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

18
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 }}

185
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)
}
}
}
}
Loading…
Cancel
Save