Browse Source

1.0.32 (#240)

* bump version

* add ws and bug fix for conversations

* fix so autocomplete works with new version of tview

* fix poll and url length
pull/242/head^2 1.0.32
Rasmus Lindroth 3 years ago committed by GitHub
parent
commit
a7305881e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      api/feed.go
  2. 45
      api/instance.go
  3. 21
      api/status.go
  4. 14
      api/stream.go
  5. 10
      api/types.go
  6. 4
      config.example.ini
  7. 2
      config/config.go
  8. 4
      config/default_config.go
  9. 2
      docs/man/tut.1
  10. 4
      docs/man/tut.1.md
  11. 10
      docs/man/tut.5
  12. 8
      docs/man/tut.5.md
  13. 2
      docs/man/tut.7
  14. 4
      docs/man/tut.7.md
  15. 26
      feed/feed.go
  16. 7
      go.mod
  17. 26
      go.sum
  18. 2
      main.go
  19. 9
      ui/cmdbar.go
  20. 21
      ui/composeview.go
  21. 13
      ui/input.go
  22. 28
      ui/item_status.go
  23. 13
      ui/pollview.go
  24. 21
      ui/tutview.go

7
api/feed.go

@ -154,6 +154,9 @@ func (ac *AccountClient) GetConversations(pg *mastodon.Pagination) ([]Item, erro
return items, err
}
for _, c := range conversations {
if c.LastStatus == nil {
continue
}
item := NewStatusItem(c.LastStatus, false)
items = append(items, item)
}
@ -165,10 +168,10 @@ func (ac *AccountClient) GetUsers(search string) ([]Item, error) {
var users []*mastodon.Account
var err error
if strings.HasPrefix(search, "@") && len(strings.Split(search, "@")) == 3 {
users, err = ac.Client.AccountsSearch(context.Background(), search, 10, true)
users, err = ac.Client.AccountsSearchResolve(context.Background(), search, 10, true)
}
if len(users) == 0 || err != nil {
users, err = ac.Client.AccountsSearch(context.Background(), search, 10, false)
users, err = ac.Client.AccountsSearchResolve(context.Background(), search, 10, false)
}
if err != nil {
return items, err

45
api/instance.go

@ -0,0 +1,45 @@
package api
func (ac *AccountClient) GetCharLimit() int {
if ac.Instance != nil {
return ac.Instance.Configuration.Statuses.MaxCharacters
}
if ac.InstanceOld == nil || ac.InstanceOld.Configuration == nil || ac.InstanceOld.Configuration.Statuses == nil {
return 500
}
s := ac.InstanceOld.Configuration.Statuses
if val, ok := (*s)["max_characters"]; ok {
return val
}
return 500
}
func (ac *AccountClient) GetLengthURL() int {
if ac.Instance != nil {
return ac.Instance.Configuration.Statuses.CharactersReservedPerURL
}
if ac.InstanceOld == nil || ac.InstanceOld.Configuration == nil || ac.InstanceOld.Configuration.Statuses == nil {
return 23
}
s := ac.InstanceOld.Configuration.Statuses
if val, ok := (*s)["characters_reserved_per_url"]; ok {
return val
}
return 23
}
func (ac *AccountClient) GetPollOptions() (options, chars int) {
if ac.Instance != nil {
return ac.Instance.Configuration.Polls.MaxOptions, ac.Instance.Configuration.Polls.MaxCharactersPerOption
}
if ac.InstanceOld == nil || ac.InstanceOld.Configuration == nil || ac.InstanceOld.Configuration.Polls == nil {
return 4, 50
}
s := ac.InstanceOld.Configuration.Polls
opts, okOne := (*s)["max_options"]
c, okTwo := (*s)["max_characters_per_option"]
if okOne && okTwo {
return opts, c
}
return 4, 50
}

21
api/status.go

@ -39,8 +39,13 @@ func toggleHelper(s *mastodon.Status, comp bool, on, off statusToggleFunc) (*mas
}
func (ac *AccountClient) BoostToggle(s *mastodon.Status) (*mastodon.Status, error) {
ns := util.StatusOrReblog(s)
reblogged := false
if ns.Reblogged != nil {
reblogged = ns.Reblogged.(bool)
}
return toggleHelper(s,
util.StatusOrReblog(s).Reblogged,
reblogged,
ac.Boost, ac.Unboost,
)
}
@ -54,8 +59,13 @@ func (ac *AccountClient) Unboost(s *mastodon.Status) (*mastodon.Status, error) {
}
func (ac *AccountClient) FavoriteToogle(s *mastodon.Status) (*mastodon.Status, error) {
ns := util.StatusOrReblog(s)
favorited := false
if ns.Favourited != nil {
favorited = ns.Favourited.(bool)
}
return toggleHelper(s,
util.StatusOrReblog(s).Favourited,
favorited,
ac.Favorite, ac.Unfavorite,
)
}
@ -71,8 +81,13 @@ func (ac *AccountClient) Unfavorite(s *mastodon.Status) (*mastodon.Status, error
}
func (ac *AccountClient) BookmarkToogle(s *mastodon.Status) (*mastodon.Status, error) {
ns := util.StatusOrReblog(s)
bookmarked := false
if ns.Bookmarked != nil {
bookmarked = ns.Bookmarked.(bool)
}
return toggleHelper(s,
util.StatusOrReblog(s).Bookmarked,
bookmarked,
ac.Bookmark, ac.Unbookmark,
)
}

14
api/stream.go

@ -81,7 +81,7 @@ func (s *Stream) RemoveReceiver(r *Receiver) {
func (s *Stream) listen() {
for e := range s.incoming {
switch e.(type) {
case *mastodon.UpdateEvent, *mastodon.NotificationEvent, *mastodon.DeleteEvent, *mastodon.ErrorEvent:
case *mastodon.UpdateEvent, *mastodon.ConversationEvent, *mastodon.NotificationEvent, *mastodon.DeleteEvent, *mastodon.ErrorEvent:
for _, r := range s.receivers {
go func(rec *Receiver, e mastodon.Event) {
rec.mux.Lock()
@ -133,17 +133,17 @@ func (ac *AccountClient) NewGenericStream(st StreamType, data string) (rec *Rece
var ch chan mastodon.Event
switch st {
case HomeStream:
ch, err = ac.Client.StreamingUser(context.Background())
ch, err = ac.WSClient.StreamingWSUser(context.Background())
case LocalStream:
ch, err = ac.Client.StreamingPublic(context.Background(), true)
ch, err = ac.WSClient.StreamingWSPublic(context.Background(), true)
case FederatedStream:
ch, err = ac.Client.StreamingPublic(context.Background(), false)
ch, err = ac.WSClient.StreamingWSPublic(context.Background(), false)
case DirectStream:
ch, err = ac.Client.StreamingDirect(context.Background())
ch, err = ac.WSClient.StreamingWSDirect(context.Background())
case TagStream:
ch, err = ac.Client.StreamingHashtag(context.Background(), data, false)
ch, err = ac.WSClient.StreamingWSHashtag(context.Background(), data, false)
case ListStream:
ch, err = ac.Client.StreamingList(context.Background(), mastodon.ID(data))
ch, err = ac.WSClient.StreamingWSList(context.Background(), mastodon.ID(data))
default:
panic("invalid StreamType")
}

10
api/types.go

@ -8,10 +8,12 @@ type RequestData struct {
}
type AccountClient struct {
Client *mastodon.Client
Streams map[string]*Stream
Me *mastodon.Account
Filters []*mastodon.Filter
Client *mastodon.Client
Streams map[string]*Stream
Me *mastodon.Account
WSClient *mastodon.WSClient
InstanceOld *mastodon.Instance
Instance *mastodon.InstanceV2
}
type User struct {

4
config.example.ini

@ -110,10 +110,6 @@ notifications-to-hide=
# default=false
quote-reply=false
# If you're on an instance with a custom character limit you can set it here.
# default=500
char-limit=500
# If you want to show icons in the list of toots.
# default=true
show-icons=true

2
config/config.go

@ -158,7 +158,6 @@ type General struct {
MaxWidth int
NotificationFeed bool
QuoteReply bool
CharLimit int
ShortHints bool
ShowFilterPhrase bool
ListPlacement ListPlacement
@ -848,7 +847,6 @@ func parseGeneral(cfg *ini.File) General {
general.NotificationFeed = cfg.Section("general").Key("notification-feed").MustBool(true)
general.QuoteReply = cfg.Section("general").Key("quote-reply").MustBool(false)
general.CharLimit = cfg.Section("general").Key("char-limit").MustInt(500)
general.MaxWidth = cfg.Section("general").Key("max-width").MustInt(0)
general.ShortHints = cfg.Section("general").Key("short-hints").MustBool(false)
general.ShowFilterPhrase = cfg.Section("general").Key("show-filter-phrase").MustBool(true)

4
config/default_config.go

@ -112,10 +112,6 @@ notifications-to-hide=
# default=false
quote-reply=false
# If you're on an instance with a custom character limit you can set it here.
# default=500
char-limit=500
# If you want to show icons in the list of toots.
# default=true
show-icons=true

2
docs/man/tut.1

@ -14,7 +14,7 @@
. ftr VB CB
. ftr VBI CBI
.\}
.TH "tut" "1" "2022-12-29" "tut 1.0.31" ""
.TH "tut" "1" "2022-12-31" "tut 1.0.32" ""
.hy
.SH NAME
.PP

4
docs/man/tut.1.md

@ -1,6 +1,6 @@
% tut(1) tut 1.0.31
% tut(1) tut 1.0.32
% Rasmus Lindroth
% 2022-12-29
% 2022-12-31
# NAME
tut - a Mastodon TUI

10
docs/man/tut.5

@ -14,7 +14,7 @@
. ftr VB CB
. ftr VBI CBI
.\}
.TH "tut" "5" "2022-12-29" "tut 1.0.31" ""
.TH "tut" "5" "2022-12-31" "tut 1.0.32" ""
.hy
.SH NAME
.PP
@ -231,14 +231,6 @@ If you always want to quote original message when replying.
.P
.PD
\f[B]quote-reply\f[R]=\f[I]false\f[R]
.SS char-limit
.PP
If you\[aq]re on an instance with a custom character limit you can set
it here.
.PD 0
.P
.PD
\f[B]char-limit\f[R]=\f[I]500\f[R]
.SS show-icons
.PP
If you want to show icons in the list of toots.

8
docs/man/tut.5.md

@ -1,6 +1,6 @@
% tut(5) tut 1.0.31
% tut(5) tut 1.0.32
% Rasmus Lindroth
% 2022-12-29
% 2022-12-31
# NAME
tut - configuration for tut(1)
@ -116,10 +116,6 @@ Hide notifications of this type. If you have multiple you separate them with a c
If you always want to quote original message when replying.
**quote-reply**=*false*
## char-limit
If you\'re on an instance with a custom character limit you can set it here.
**char-limit**=*500*
## show-icons
If you want to show icons in the list of toots.
**show-icons**=*true*

2
docs/man/tut.7

@ -14,7 +14,7 @@
. ftr VB CB
. ftr VBI CBI
.\}
.TH "tut" "7" "2022-12-29" "tut 1.0.31" ""
.TH "tut" "7" "2022-12-31" "tut 1.0.32" ""
.hy
.SH NAME
.PP

4
docs/man/tut.7.md

@ -1,6 +1,6 @@
% tut(7) tut 1.0.31
% tut(7) tut 1.0.32
% Rasmus Lindroth
% 2022-12-29
% 2022-12-31
# NAME
tut - keys and commands inside of tut(1)

26
feed/feed.go

@ -694,6 +694,32 @@ func (f *Feed) startStream(rec *api.Receiver, timeline string, err error) {
go func() {
for e := range rec.Ch {
switch t := e.(type) {
case *mastodon.ConversationEvent:
if t.Conversation.LastStatus == nil {
continue
}
s := api.NewStatusItem(t.Conversation.LastStatus, false)
f.itemsMux.Lock()
found := false
if len(f.streams) > 0 {
for _, item := range f.items {
switch v := item.Raw().(type) {
case *mastodon.Status:
if t.Conversation.LastStatus.ID == v.ID {
found = true
break
}
}
}
}
if !found {
f.items = append([]api.Item{s}, f.items...)
f.Updated(DesktopNotificationHolder{
Type: DesktopNotificationMention,
})
f.apiData.MinID = t.Conversation.LastStatus.ID
}
f.itemsMux.Unlock()
case *mastodon.UpdateEvent:
s := api.NewStatusItem(t.Status, false)
f.itemsMux.Lock()

7
go.mod

@ -3,7 +3,7 @@ module github.com/RasmusLindroth/tut
go 1.18
require (
github.com/RasmusLindroth/go-mastodon v0.0.17
github.com/RasmusLindroth/go-mastodon v0.0.20
github.com/adrg/xdg v0.4.0
github.com/atotto/clipboard v0.1.4
github.com/gdamore/tcell/v2 v2.5.3
@ -12,12 +12,13 @@ require (
github.com/icza/gox v0.0.0-20221026131554-a08a8cdc726a
github.com/microcosm-cc/bluemonday v1.0.21
github.com/pelletier/go-toml/v2 v2.0.6
github.com/rivo/tview v0.0.0-20221221172820-02e38ea9604c
github.com/rivo/tview v0.0.0-20221229180733-b86a50a5126c
github.com/rivo/uniseg v0.4.3
github.com/spf13/pflag v1.0.5
golang.org/x/exp v0.0.0-20221227203929-1b447090c38c
golang.org/x/exp v0.0.0-20221230185412-738e83a70c30
golang.org/x/net v0.4.0
gopkg.in/ini.v1 v1.67.0
mvdan.cc/xurls/v2 v2.4.0
)
require (

26
go.sum

@ -1,5 +1,5 @@
github.com/RasmusLindroth/go-mastodon v0.0.17 h1:PUR4YS9ORe62ZSabvZVwxROZvrcMuNVC/8Y/D/d6dFQ=
github.com/RasmusLindroth/go-mastodon v0.0.17/go.mod h1:Lr6n8V1U2b+9P89YZKsICkNc+oNeJXkygY7raei9SXE=
github.com/RasmusLindroth/go-mastodon v0.0.20 h1:xnFiSV7DfMCF8VOEn6QVbk94bGXxxAiUlw3Grby6ofw=
github.com/RasmusLindroth/go-mastodon v0.0.20/go.mod h1:Lr6n8V1U2b+9P89YZKsICkNc+oNeJXkygY7raei9SXE=
github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls=
github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E=
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
@ -27,6 +27,9 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/icza/gox v0.0.0-20221026131554-a08a8cdc726a h1:ctOSka++0Y+9xF7VLtZ8TOJjyXjOGYywzuhbzj3IEHw=
github.com/icza/gox v0.0.0-20221026131554-a08a8cdc726a/go.mod h1:VbcN86fRkkUMPX2ufM85Um8zFndLZswoIW1eYtpAcVk=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
@ -38,15 +41,15 @@ github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/tview v0.0.0-20221217182043-ccce554c3803 h1:gaknGRzW4g4I+5sGu4X81BZbROJ0j96ap9xnEbcZhXA=
github.com/rivo/tview v0.0.0-20221217182043-ccce554c3803/go.mod h1:YX2wUZOcJGOIycErz2s9KvDaP0jnWwRCirQMPLPpQ+Y=
github.com/rivo/tview v0.0.0-20221221172820-02e38ea9604c h1:Y4GSXEYKYAtguH10lmQmYb7hRkJ7U+m8GvnFHKU2jrk=
github.com/rivo/tview v0.0.0-20221221172820-02e38ea9604c/go.mod h1:lBUy/T5kyMudFzWUH/C2moN+NlU5qF505vzOyINXuUQ=
github.com/rivo/tview v0.0.0-20221229180733-b86a50a5126c h1:Xa0IDAwI/b4D3AQwFOhvOeYB/H0N8Bhhe3XJWSa2vjg=
github.com/rivo/tview v0.0.0-20221229180733-b86a50a5126c/go.mod h1:lBUy/T5kyMudFzWUH/C2moN+NlU5qF505vzOyINXuUQ=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw=
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -61,12 +64,11 @@ 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=
golang.org/x/exp v0.0.0-20221217163422-3c43f8badb15 h1:5oN1Pz/eDhCpbMbLstvIPa0b/BEQo6g6nwV3pLjfM6w=
golang.org/x/exp v0.0.0-20221217163422-3c43f8badb15/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/exp v0.0.0-20221227203929-1b447090c38c h1:Govq2W3bnHJimHT2ium65kXcI7ZzTniZHcFATnLJM0Q=
golang.org/x/exp v0.0.0-20221227203929-1b447090c38c/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/exp v0.0.0-20221230185412-738e83a70c30 h1:m9O6OTJ627iFnN2JIWfdqlZCzneRO6EEBsHXI25P8ws=
golang.org/x/exp v0.0.0-20221230185412-738e83a70c30/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220318055525-2edf467146b5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -82,8 +84,12 @@ golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
mvdan.cc/xurls/v2 v2.4.0 h1:tzxjVAj+wSBmDcF6zBB7/myTy3gX9xvi8Tyr28AuQgc=
mvdan.cc/xurls/v2 v2.4.0/go.mod h1:+GEjq9uNjqs8LQfM9nVnM8rff0OQ5Iash5rzX+N1CSg=

2
main.go

@ -8,7 +8,7 @@ import (
"github.com/rivo/tview"
)
const version = "1.0.31"
const version = "1.0.32"
func main() {
util.SetTerminalTitle("tut")

9
ui/cmdbar.go

@ -19,6 +19,7 @@ func NewCmdBar(tv *TutView) *CmdBar {
View: NewInputField(tv.tut.Config),
}
c.View.SetAutocompleteFunc(c.Autocomplete)
c.View.SetAutocompletedFunc(c.Autocompleted)
c.View.SetDoneFunc(c.DoneFunc)
return c
@ -313,3 +314,11 @@ func (c *CmdBar) Autocomplete(curr string) []string {
}
return entries
}
func (c *CmdBar) Autocompleted(text string, index, source int) bool {
if source != tview.AutocompletedNavigate {
c.View.SetText(text)
}
return source == tview.AutocompletedEnter || source == tview.AutocompletedClick
}

21
ui/composeview.go

@ -15,6 +15,7 @@ import (
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
"github.com/rivo/uniseg"
"mvdan.cc/xurls/v2"
)
type msgToot struct {
@ -102,15 +103,33 @@ const (
ComposeMedia
)
func urlsInText(txt string) (count, length int) {
x := xurls.Strict()
matches := x.FindAllString(txt, -1)
count = len(matches)
for _, m := range matches {
length += len(m)
}
return
}
func (cv *ComposeView) msgLength() int {
m := cv.msg
charCount := uniseg.GraphemeClusterCount(m.Text)
spoilerCount := uniseg.GraphemeClusterCount(m.CWText)
totalCount := charCount
urlLength := cv.tutView.tut.Client.GetLengthURL()
urls, length := urlsInText(m.Text)
if urls > 0 {
totalCount = totalCount - length
totalCount = totalCount + (urls * urlLength)
}
if m.Sensitive {
totalCount += spoilerCount
}
charsLeft := cv.tutView.tut.Config.General.CharLimit - totalCount
charsLeft := cv.tutView.tut.Client.GetCharLimit() - totalCount
return charsLeft
}

13
ui/input.go

@ -381,9 +381,16 @@ func (tv *TutView) InputStatus(event *tcell.EventKey, item api.Item, status *mas
hasSpoiler := sr.Sensitive
isMine := sr.Account.ID == tv.tut.Client.Me.ID
boosted := sr.Reblogged
favorited := sr.Favourited
bookmarked := sr.Bookmarked
boosted, favorited, bookmarked := false, false, false
if sr.Reblogged != nil {
boosted = sr.Reblogged.(bool)
}
if sr.Favourited != nil {
favorited = sr.Favourited.(bool)
}
if sr.Bookmarked != nil {
bookmarked = sr.Bookmarked.(bool)
}
if tv.tut.Config.Input.StatusAvatar.Match(event.Key(), event.Rune()) {
if nAcc != nil {

28
ui/item_status.go

@ -124,7 +124,10 @@ func drawStatus(tv *TutView, item api.Item, status *mastodon.Status, main *tview
toot.AccountDisplayName = tview.Escape(status.Account.DisplayName)
toot.Account = tview.Escape(status.Account.Acct)
toot.Bookmarked = status.Bookmarked
toot.Bookmarked = false
if status.Bookmarked != nil {
toot.Bookmarked = status.Bookmarked.(bool)
}
toot.Visibility = status.Visibility
toot.Spoiler = status.Sensitive
toot.Edited = status.CreatedAt.Before(status.EditedAt)
@ -198,14 +201,25 @@ func drawStatus(tv *TutView, item api.Item, status *mastodon.Status, main *tview
}
var info []Control
if status.Favourited && !isHistory {
statusFavorited, statusBoosted, statusBookmarked := false, false, false
if status.Favourited != nil {
statusFavorited = status.Favourited.(bool)
}
if status.Reblogged != nil {
statusBoosted = status.Reblogged.(bool)
}
if status.Bookmarked != nil {
statusBookmarked = status.Bookmarked.(bool)
}
if statusFavorited && !isHistory {
info = append(info, NewControl(tv.tut.Config, tv.tut.Config.Input.StatusFavorite, false))
} else if !status.Favourited && !isHistory {
} else if !statusFavorited && !isHistory {
info = append(info, NewControl(tv.tut.Config, tv.tut.Config.Input.StatusFavorite, true))
}
if status.Reblogged && !isHistory {
if statusBoosted && !isHistory {
info = append(info, NewControl(tv.tut.Config, tv.tut.Config.Input.StatusBoost, false))
} else if !status.Reblogged && !isHistory {
} else if !statusBoosted && !isHistory {
info = append(info, NewControl(tv.tut.Config, tv.tut.Config.Input.StatusBoost, true))
}
if !isHistory {
@ -229,9 +243,9 @@ func drawStatus(tv *TutView, item api.Item, status *mastodon.Status, main *tview
info = append(info, NewControl(tv.tut.Config, tv.tut.Config.Input.StatusDelete, true))
}
if !status.Bookmarked && !isHistory {
if !statusBookmarked && !isHistory {
info = append(info, NewControl(tv.tut.Config, tv.tut.Config.Input.StatusBookmark, true))
} else if status.Bookmarked && !isHistory {
} else if statusBookmarked && !isHistory {
info = append(info, NewControl(tv.tut.Config, tv.tut.Config.Input.StatusBookmark, false))
}
if !isHistory {

13
ui/pollview.go

@ -38,9 +38,12 @@ type PollView struct {
list *tview.List
poll *mastodon.TootPoll
scrollSleep *scrollSleep
numOptions int
numChars int
}
func NewPollView(tv *TutView) *PollView {
options, chars := tv.tut.Client.GetPollOptions()
p := &PollView{
tutView: tv,
shared: tv.Shared,
@ -48,6 +51,8 @@ func NewPollView(tv *TutView) *PollView {
expiration: NewDropDown(tv.tut.Config),
controls: NewControlView(tv.tut.Config),
list: NewList(tv.tut.Config),
numOptions: options,
numChars: chars,
}
p.scrollSleep = NewScrollSleep(p.Next, p.Prev)
p.Reset()
@ -157,11 +162,11 @@ func (p *PollView) Next() {
}
func (p *PollView) Add() {
if p.list.GetItemCount() > 3 {
p.tutView.ShowError("You can only have a maximum of 4 options.")
if p.list.GetItemCount() > p.numOptions-1 {
p.tutView.ShowError(fmt.Sprintf("You can only have a maximum of %d options.", p.numOptions))
return
}
text, valid, err := OpenEditorLengthLimit(p.tutView, "", 25)
text, valid, err := OpenEditorLengthLimit(p.tutView, "", p.numChars)
if err != nil {
p.tutView.ShowError(
fmt.Sprintf("Couldn't open editor. Error: %v", err),
@ -182,7 +187,7 @@ func (p *PollView) Edit() {
return
}
text, _ := p.list.GetItemText(p.list.GetCurrentItem())
text, valid, err := OpenEditorLengthLimit(p.tutView, text, 25)
text, valid, err := OpenEditorLengthLimit(p.tutView, text, p.numChars)
if err != nil {
p.tutView.ShowError(
fmt.Sprintf("Couldn't open editor. Error: %v", err),

21
ui/tutview.go

@ -151,12 +151,23 @@ func (tv *TutView) loggedIn(acc auth.Account) {
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,
Me: me,
Client: client,
Streams: make(map[string]*api.Stream),
WSClient: client.NewWSClient(),
}
inst, err := ac.Client.GetInstanceV2(context.Background())
if err != nil {
inst, err := ac.Client.GetInstance(context.Background())
if err != nil {
fmt.Printf("Couldn't get instance. Error %s\n", err)
tv.tut.App.Stop()
tv.CleanExit(1)
}
ac.InstanceOld = inst
} else {
ac.Instance = inst
}
tv.tut.Client = ac

Loading…
Cancel
Save