Browse Source

32 (#79)

* add icons (#78)

* add support for lists

* update version

* update readme
pull/82/head 0.0.32
Rasmus Lindroth 5 years ago committed by GitHub
parent
commit
7d33f68fb1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      README.md
  2. 31
      api.go
  3. 13
      authoverlay.go
  4. 16
      cmdbar.go
  5. 4
      config.example.ini
  6. 8
      config.go
  7. 214
      feed.go
  8. 2
      linkoverlay.go
  9. 6
      main.go
  10. 17
      notifications.go
  11. 86
      statusview.go
  12. 27
      ui.go
  13. 14
      util.go

1
README.md

@ -33,6 +33,7 @@ You can find Linux binaries under [releases](https://github.com/RasmusLindroth/t
* `:compose` compose a new toot
* `:favorited` lists toots you've favorited
* `:favorites` lists users that favorited the toot
* `:lists` show a list of your lists
* `:muting` lists users that you have muted
* `:profile` go to your profile
* `:saved` alias for bookmarks

31
api.go

@ -17,6 +17,7 @@ const (
TimelineFederated
TimelineBookmarked
TimelineFavorited
TimelineList
)
type UserListType uint
@ -44,7 +45,7 @@ func (api *API) SetClient(c *mastodon.Client) {
api.Client = c
}
func (api *API) getStatuses(tl TimelineType, pg *mastodon.Pagination) ([]*mastodon.Status, mastodon.ID, mastodon.ID, error) {
func (api *API) getStatuses(tl TimelineType, listInfo *ListInfo, pg *mastodon.Pagination) ([]*mastodon.Status, mastodon.ID, mastodon.ID, error) {
var err error
var statuses []*mastodon.Status
@ -71,8 +72,14 @@ func (api *API) getStatuses(tl TimelineType, pg *mastodon.Pagination) ([]*mastod
statuses, err = api.Client.GetBookmarks(context.Background(), pg)
case TimelineFavorited:
statuses, err = api.Client.GetFavourites(context.Background(), pg)
case TimelineList:
if listInfo == nil {
err = errors.New("no list id")
return statuses, "", "", err
}
statuses, err = api.Client.GetTimelineList(context.Background(), listInfo.id, pg)
default:
err = errors.New("No timeline selected")
err = errors.New("no timeline selected")
}
if err != nil {
@ -95,7 +102,7 @@ func (api *API) getStatuses(tl TimelineType, pg *mastodon.Pagination) ([]*mastod
}
func (api *API) GetStatuses(t *TimelineFeed) ([]*mastodon.Status, error) {
statuses, pgmin, pgmax, err := api.getStatuses(t.timelineType, nil)
statuses, pgmin, pgmax, err := api.getStatuses(t.timelineType, t.listInfo, nil)
switch t.timelineType {
case TimelineBookmarked, TimelineFavorited:
if err == nil {
@ -119,7 +126,7 @@ func (api *API) GetStatusesOlder(t *TimelineFeed) ([]*mastodon.Status, error) {
pg := &mastodon.Pagination{
MaxID: t.linkNext,
}
statuses, _, max, err := api.getStatuses(t.timelineType, pg)
statuses, _, max, err := api.getStatuses(t.timelineType, t.listInfo, pg)
if err == nil {
t.linkNext = max
}
@ -128,7 +135,7 @@ func (api *API) GetStatusesOlder(t *TimelineFeed) ([]*mastodon.Status, error) {
pg := &mastodon.Pagination{
MaxID: t.statuses[len(t.statuses)-1].ID,
}
statuses, _, _, err := api.getStatuses(t.timelineType, pg)
statuses, _, _, err := api.getStatuses(t.timelineType, t.listInfo, pg)
return statuses, err
}
}
@ -146,7 +153,7 @@ func (api *API) GetStatusesNewer(t *TimelineFeed) ([]*mastodon.Status, error) {
pg := &mastodon.Pagination{
MinID: mastodon.ID(t.linkPrev),
}
statuses, min, _, err := api.getStatuses(t.timelineType, pg)
statuses, min, _, err := api.getStatuses(t.timelineType, t.listInfo, pg)
if err == nil {
t.linkPrev = min
}
@ -155,7 +162,7 @@ func (api *API) GetStatusesNewer(t *TimelineFeed) ([]*mastodon.Status, error) {
pg := &mastodon.Pagination{
MinID: t.statuses[0].ID,
}
statuses, _, _, err := api.getStatuses(t.timelineType, pg)
statuses, _, _, err := api.getStatuses(t.timelineType, t.listInfo, pg)
return statuses, err
}
}
@ -357,9 +364,13 @@ func (api *API) GetUserByID(id mastodon.ID) (*mastodon.Account, error) {
return a, err
}
func (api *API) GetLists() ([]*mastodon.List, error) {
return api.Client.GetLists(context.Background())
}
func (api *API) BoostToggle(s *mastodon.Status) (*mastodon.Status, error) {
if s == nil {
return nil, fmt.Errorf("No status")
return nil, fmt.Errorf("no status")
}
if s.Reblogged == true {
@ -380,7 +391,7 @@ func (api *API) Unboost(s *mastodon.Status) (*mastodon.Status, error) {
func (api *API) FavoriteToogle(s *mastodon.Status) (*mastodon.Status, error) {
if s == nil {
return nil, fmt.Errorf("No status")
return nil, fmt.Errorf("no status")
}
if s.Favourited == true {
@ -401,7 +412,7 @@ func (api *API) Unfavorite(s *mastodon.Status) (*mastodon.Status, error) {
func (api *API) BookmarkToogle(s *mastodon.Status) (*mastodon.Status, error) {
if s == nil {
return nil, fmt.Errorf("No status")
return nil, fmt.Errorf("no status")
}
if s.Bookmarked == true {

13
authoverlay.go

@ -37,13 +37,12 @@ func NewAuthOverlay(app *App) *AuthOverlay {
}
type AuthOverlay struct {
app *App
Flex *tview.Flex
Input *tview.InputField
Text *tview.TextView
authStep authStep
account AccountRegister
redirectURL string
app *App
Flex *tview.Flex
Input *tview.InputField
Text *tview.TextView
authStep authStep
account AccountRegister
}
func (a *AuthOverlay) GotInput() {

16
cmdbar.go

@ -64,11 +64,11 @@ func (c *CmdBar) DoneFunc(key tcell.Key) {
c.app.UI.SetFocus(LeftPaneFocus)
c.app.UI.CmdBar.ClearInput()
case ":bookmarks", ":saved":
c.app.UI.StatusView.AddFeed(NewTimelineFeed(c.app, TimelineBookmarked))
c.app.UI.StatusView.AddFeed(NewTimelineFeed(c.app, TimelineBookmarked, nil))
c.app.UI.SetFocus(LeftPaneFocus)
c.app.UI.CmdBar.ClearInput()
case ":favorited":
c.app.UI.StatusView.AddFeed(NewTimelineFeed(c.app, TimelineFavorited))
c.app.UI.StatusView.AddFeed(NewTimelineFeed(c.app, TimelineFavorited, nil))
c.app.UI.SetFocus(LeftPaneFocus)
c.app.UI.CmdBar.ClearInput()
case ":boosts":
@ -129,19 +129,19 @@ func (c *CmdBar) DoneFunc(key tcell.Key) {
}
switch parts[1] {
case "local", "l":
c.app.UI.StatusView.AddFeed(NewTimelineFeed(c.app, TimelineLocal))
c.app.UI.StatusView.AddFeed(NewTimelineFeed(c.app, TimelineLocal, nil))
c.app.UI.SetFocus(LeftPaneFocus)
c.app.UI.CmdBar.ClearInput()
case "federated", "f":
c.app.UI.StatusView.AddFeed(NewTimelineFeed(c.app, TimelineFederated))
c.app.UI.StatusView.AddFeed(NewTimelineFeed(c.app, TimelineFederated, nil))
c.app.UI.SetFocus(LeftPaneFocus)
c.app.UI.CmdBar.ClearInput()
case "direct", "d":
c.app.UI.StatusView.AddFeed(NewTimelineFeed(c.app, TimelineDirect))
c.app.UI.StatusView.AddFeed(NewTimelineFeed(c.app, TimelineDirect, nil))
c.app.UI.SetFocus(LeftPaneFocus)
c.app.UI.CmdBar.ClearInput()
case "home", "h":
c.app.UI.StatusView.AddFeed(NewTimelineFeed(c.app, TimelineHome))
c.app.UI.StatusView.AddFeed(NewTimelineFeed(c.app, TimelineHome, nil))
c.app.UI.SetFocus(LeftPaneFocus)
c.app.UI.CmdBar.ClearInput()
case "notifications", "n":
@ -175,5 +175,9 @@ func (c *CmdBar) DoneFunc(key tcell.Key) {
c.app.UI.StatusView.AddFeed(NewUserListFeed(c.app, UserListSearch, user))
c.app.UI.SetFocus(LeftPaneFocus)
c.app.UI.CmdBar.ClearInput()
case ":lists":
c.app.UI.StatusView.AddFeed(NewListFeed(c.app))
c.app.UI.SetFocus(LeftPaneFocus)
c.app.UI.CmdBar.ClearInput()
}
}

4
config.example.ini

@ -84,6 +84,10 @@ quote-reply=false
# default=500
char-limit=500
# If you want to show icons in the list of toots
# default=true
show-icons=true
# If you've learnt all the shortcut keys you can remove the help text and
# only show the key in tui. So it gets less cluttered.
# default=false

8
config.go

@ -36,6 +36,7 @@ type GeneralConfig struct {
HideNotificationText bool
ListProportion int
ContentProportion int
ShowIcons bool
}
type StyleConfig struct {
@ -266,6 +267,7 @@ func parseGeneral(cfg *ini.File) GeneralConfig {
general.CharLimit = cfg.Section("general").Key("char-limit").MustInt(500)
general.ShortHints = cfg.Section("general").Key("short-hints").MustBool(false)
general.HideNotificationText = cfg.Section("general").Key("hide-notification-text").MustBool(false)
general.ShowIcons = cfg.Section("general").Key("show-icons").MustBool(true)
lp := cfg.Section("general").Key("list-placement").In("left", []string{"left", "right", "top", "bottom"})
switch lp {
@ -554,6 +556,10 @@ quote-reply=false
# default=500
char-limit=500
# If you want to show icons in the list of toots
# default=true
show-icons=true
# If you've learnt all the shortcut keys you can remove the help text and
# only show the key in tui. So it gets less cluttered.
# default=false
@ -744,10 +750,10 @@ list-selected-background=xrdb:color5
list-selected-text=xrdb:background
`
f, err := os.Create(filepath)
defer f.Close()
if err != nil {
return err
}
defer f.Close()
_, err = f.WriteString(conf)
if err != nil {
return err

214
feed.go

@ -20,10 +20,11 @@ const (
UserSearchFeedType
NotificationFeedType
TagFeedType
ListFeedType
)
type Feed interface {
GetFeedList() <-chan string
GetFeedList() <-chan ListItem
LoadNewer() int
LoadOlder() int
DrawList()
@ -258,8 +259,8 @@ func showUser(app *App, user *mastodon.Account, relation *mastodon.Relationship,
return text, controls
}
func drawStatusList(statuses []*mastodon.Status, longFormat, shortFormat string, relativeDate int) <-chan string {
ch := make(chan string)
func drawStatusList(statuses []*mastodon.Status, longFormat, shortFormat string, relativeDate int) <-chan ListItem {
ch := make(chan ListItem)
go func() {
today := time.Now()
for _, s := range statuses {
@ -267,7 +268,15 @@ func drawStatusList(statuses []*mastodon.Status, longFormat, shortFormat string,
dateOutput := OutputDate(sLocal, today, longFormat, shortFormat, relativeDate)
content := fmt.Sprintf("%s %s", dateOutput, s.Account.Acct)
ch <- content
iconText := ""
rs := s
if s.Reblog != nil {
rs = s.Reblog
}
if rs.RepliesCount > 0 {
iconText = " ⤶ "
}
ch <- ListItem{Text: content, Icons: iconText}
}
close(ch)
}()
@ -291,8 +300,10 @@ const (
ControlBoost
ControlCompose
ControlDelete
ControlEnter
ControlFavorite
ControlFollow
ControlList
ControlMedia
ControlMute
ControlOpen
@ -312,16 +323,33 @@ func inputOptions(options []ControlItem) ControlItem {
}
func inputSimple(app *App, event *tcell.EventKey, controls ControlItem,
user mastodon.Account, status *mastodon.Status, originalStatus *mastodon.Status, relation *mastodon.Relationship, feed Feed) (updated bool,
user mastodon.Account, status *mastodon.Status, originalStatus *mastodon.Status, relation *mastodon.Relationship, feed Feed, listInfo *ListInfo) (updated bool,
redrawControls bool, redrawToot bool, newStatus *mastodon.Status, newRelation *mastodon.Relationship) {
newStatus = status
newRelation = relation
var err error
if event.Key() == tcell.KeyEnter {
if controls&ControlEnter == 0 {
return
}
if controls&ControlUser != 0 {
app.UI.StatusView.AddFeed(
NewUserFeed(app, user),
)
}
if controls&ControlList != 0 {
app.UI.StatusView.AddFeed(
NewTimelineFeed(app, TimelineList, listInfo),
)
}
}
if event.Key() != tcell.KeyRune {
return
}
switch event.Rune() {
case 'a', 'A':
if controls&ControlAvatar != 0 {
@ -418,6 +446,11 @@ func inputSimple(app *App, event *tcell.EventKey, controls ControlItem,
if controls&ControlOpen != 0 {
app.UI.ShowLinks()
}
if controls&ControlList != 0 {
app.UI.StatusView.AddFeed(
NewTimelineFeed(app, TimelineList, listInfo),
)
}
case 'r', 'R':
if controls&ControlReply != 0 {
app.UI.Reply(status)
@ -469,12 +502,13 @@ func userFromStatus(s *mastodon.Status) *mastodon.Account {
return &s.Account
}
func NewTimelineFeed(app *App, tl TimelineType) *TimelineFeed {
func NewTimelineFeed(app *App, tl TimelineType, listInfo *ListInfo) *TimelineFeed {
t := &TimelineFeed{
app: app,
timelineType: tl,
linkPrev: "",
linkNext: "",
listInfo: listInfo,
}
var err error
t.statuses, err = t.app.API.GetStatuses(t)
@ -490,6 +524,7 @@ type TimelineFeed struct {
statuses []*mastodon.Status
linkPrev mastodon.ID //Only bm and fav
linkNext mastodon.ID //Only bm and fav
listInfo *ListInfo //only lists
index int
showSpoiler bool
}
@ -512,6 +547,8 @@ func (t *TimelineFeed) GetDesc() string {
return "Bookmarks"
case TimelineFavorited:
return "Favorited"
case TimelineList:
return fmt.Sprintf("List: %s", t.listInfo.name)
}
return "Timeline"
}
@ -528,7 +565,7 @@ func (t *TimelineFeed) GetCurrentUser() *mastodon.Account {
return userFromStatus(t.GetCurrentStatus())
}
func (t *TimelineFeed) GetFeedList() <-chan string {
func (t *TimelineFeed) GetFeedList() <-chan ListItem {
return drawStatusList(t.statuses, t.app.Config.General.DateFormat, t.app.Config.General.DateTodayFormat, t.app.Config.General.DateRelative)
}
@ -629,7 +666,7 @@ func (t *TimelineFeed) Input(event *tcell.EventKey) {
}
options := inputOptions(controls)
updated, rc, rt, newS, _ := inputSimple(t.app, event, options, user, status, originalStatus, nil, t)
updated, rc, rt, newS, _ := inputSimple(t.app, event, options, user, status, originalStatus, nil, t, nil)
if updated {
index := t.app.UI.StatusView.GetCurrentItem()
t.statuses[index] = newS
@ -684,7 +721,7 @@ func (t *ThreadFeed) GetCurrentUser() *mastodon.Account {
return userFromStatus(t.GetCurrentStatus())
}
func (t *ThreadFeed) GetFeedList() <-chan string {
func (t *ThreadFeed) GetFeedList() <-chan ListItem {
return drawStatusList(t.statuses, t.app.Config.General.DateFormat, t.app.Config.General.DateTodayFormat, t.app.Config.General.DateRelative)
}
@ -755,7 +792,7 @@ func (t *ThreadFeed) Input(event *tcell.EventKey) {
}
options := inputOptions(controls)
updated, rc, rt, newS, _ := inputSimple(t.app, event, options, user, status, originalStatus, nil, t)
updated, rc, rt, newS, _ := inputSimple(t.app, event, options, user, status, originalStatus, nil, t, nil)
if updated {
index := t.app.UI.StatusView.GetCurrentItem()
t.statuses[index] = newS
@ -817,10 +854,10 @@ func (u *UserFeed) GetCurrentUser() *mastodon.Account {
return &u.user
}
func (u *UserFeed) GetFeedList() <-chan string {
ch := make(chan string)
func (u *UserFeed) GetFeedList() <-chan ListItem {
ch := make(chan ListItem)
go func() {
ch <- "Profile"
ch <- ListItem{Text: "Profile", Icons: ""}
for s := range drawStatusList(u.statuses, u.app.Config.General.DateFormat, u.app.Config.General.DateTodayFormat, u.app.Config.General.DateRelative) {
ch <- s
}
@ -924,7 +961,7 @@ func (u *UserFeed) Input(event *tcell.EventKey) {
}
options := inputOptions(controls)
updated, _, _, _, newRel := inputSimple(u.app, event, options, u.user, nil, nil, u.relation, u)
updated, _, _, _, newRel := inputSimple(u.app, event, options, u.user, nil, nil, u.relation, u, nil)
if updated {
u.relation = newRel
u.DrawToot()
@ -949,7 +986,7 @@ func (u *UserFeed) Input(event *tcell.EventKey) {
}
options := inputOptions(controls)
updated, rc, rt, newS, _ := inputSimple(u.app, event, options, user, status, originalStatus, nil, u)
updated, rc, rt, newS, _ := inputSimple(u.app, event, options, user, status, originalStatus, nil, u, nil)
if updated {
index := u.app.UI.StatusView.GetCurrentItem()
u.statuses[index-1] = newS
@ -978,7 +1015,6 @@ type Notification struct {
type NotificationsFeed struct {
app *App
timelineType TimelineType
notifications []*Notification
docked bool
index int
@ -1022,8 +1058,8 @@ func (n *NotificationsFeed) GetCurrentUser() *mastodon.Account {
return &notification.N.Account
}
func (n *NotificationsFeed) GetFeedList() <-chan string {
ch := make(chan string)
func (n *NotificationsFeed) GetFeedList() <-chan ListItem {
ch := make(chan ListItem)
notifications := n.notifications
go func() {
today := time.Now()
@ -1035,8 +1071,22 @@ func (n *NotificationsFeed) GetFeedList() <-chan string {
dateOutput := OutputDate(sLocal, today, long, short, relative)
iconText := ""
switch item.N.Type {
case "follow", "follow_request":
iconText += " + "
case "favourite":
iconText = " ★ "
case "reblog":
iconText = " ♺ "
case "mention":
iconText = " ⤶ "
case "poll":
iconText = " = "
}
content := fmt.Sprintf("%s %s", dateOutput, item.N.Account.Acct)
ch <- content
ch <- ListItem{Text: content, Icons: iconText}
}
close(ch)
}()
@ -1190,7 +1240,7 @@ func (n *NotificationsFeed) Input(event *tcell.EventKey) {
if notification.N.Type == "follow" {
controls := []ControlItem{ControlUser, ControlFollow, ControlBlock, ControlMute, ControlAvatar, ControlOpen}
options := inputOptions(controls)
_, rc, _, _, rel := inputSimple(n.app, event, options, notification.N.Account, nil, nil, notification.R, n)
_, rc, _, _, rel := inputSimple(n.app, event, options, notification.N.Account, nil, nil, notification.R, n, nil)
if rc {
var index int
if n.docked {
@ -1220,7 +1270,7 @@ func (n *NotificationsFeed) Input(event *tcell.EventKey) {
}
options := inputOptions(controls)
updated, rc, rt, newS, _ := inputSimple(n.app, event, options, notification.N.Account, status, originalStatus, nil, n)
updated, rc, rt, newS, _ := inputSimple(n.app, event, options, notification.N.Account, status, originalStatus, nil, n, nil)
if updated {
var index int
if n.docked {
@ -1275,7 +1325,7 @@ func (t *TagFeed) GetCurrentUser() *mastodon.Account {
return userFromStatus(t.GetCurrentStatus())
}
func (t *TagFeed) GetFeedList() <-chan string {
func (t *TagFeed) GetFeedList() <-chan ListItem {
return drawStatusList(t.statuses, t.app.Config.General.DateFormat, t.app.Config.General.DateTodayFormat, t.app.Config.General.DateRelative)
}
@ -1371,7 +1421,7 @@ func (t *TagFeed) Input(event *tcell.EventKey) {
}
options := inputOptions(controls)
updated, rc, rt, newS, _ := inputSimple(t.app, event, options, user, status, originalStatus, nil, t)
updated, rc, rt, newS, _ := inputSimple(t.app, event, options, user, status, originalStatus, nil, t, nil)
if updated {
index := t.app.UI.StatusView.GetCurrentItem()
t.statuses[index] = newS
@ -1452,8 +1502,8 @@ func (u *UserListFeed) GetCurrentUserData() *UserData {
return u.users[index-1]
}
func (u *UserListFeed) GetFeedList() <-chan string {
ch := make(chan string)
func (u *UserListFeed) GetFeedList() <-chan ListItem {
ch := make(chan ListItem)
users := u.users
go func() {
for _, user := range users {
@ -1463,7 +1513,7 @@ func (u *UserListFeed) GetFeedList() <-chan string {
} else {
username = fmt.Sprintf("%s (%s)", user.User.DisplayName, user.User.Acct)
}
ch <- username
ch <- ListItem{Text: username, Icons: ""}
}
close(ch)
}()
@ -1547,13 +1597,121 @@ func (u *UserListFeed) Input(event *tcell.EventKey) {
user := u.users[index]
controls := []ControlItem{
ControlAvatar, ControlFollow, ControlBlock, ControlMute, ControlOpen, ControlUser,
ControlAvatar, ControlFollow, ControlBlock, ControlMute, ControlOpen,
ControlUser, ControlEnter,
}
options := inputOptions(controls)
updated, _, _, _, newRel := inputSimple(u.app, event, options, *user.User, nil, nil, user.Relationship, u)
updated, _, _, _, newRel := inputSimple(u.app, event, options, *user.User, nil, nil, user.Relationship, u, nil)
if updated {
u.users[index].Relationship = newRel
u.DrawToot()
}
}
func NewListFeed(app *App) *ListFeed {
l := &ListFeed{
app: app,
}
lists, err := app.API.GetLists()
if err != nil {
l.app.UI.CmdBar.ShowError(fmt.Sprintf("Couldn't load lists. Error: %v\n", err))
return l
}
l.lists = lists
return l
}
type ListInfo struct {
name string
id mastodon.ID
}
type ListFeed struct {
app *App
lists []*mastodon.List
index int
}
func (l *ListFeed) FeedType() FeedType {
return ListFeedType
}
func (l *ListFeed) GetDesc() string {
return "Lists"
}
func (l *ListFeed) GetCurrentStatus() *mastodon.Status {
return nil
}
func (l *ListFeed) GetCurrentUser() *mastodon.Account {
return nil
}
func (l *ListFeed) GetFeedList() <-chan ListItem {
ch := make(chan ListItem)
go func() {
for _, list := range l.lists {
ch <- ListItem{Text: list.Title, Icons: ""}
}
close(ch)
}()
return ch
}
func (l *ListFeed) LoadNewer() int {
return 0
}
func (l *ListFeed) LoadOlder() int {
return 0
}
func (l *ListFeed) DrawList() {
l.app.UI.StatusView.SetList(l.GetFeedList())
}
func (l *ListFeed) RedrawControls() {
//Does not implement
}
func (l *ListFeed) DrawSpoiler() {
//Does not implement
}
func (l *ListFeed) DrawToot() {
l.index = l.app.UI.StatusView.GetCurrentItem()
index := l.index
if index > len(l.lists)-1 || len(l.lists) == 0 {
return
}
list := l.lists[index]
text := ColorKey(l.app.Config, "", "O", "pen")
text += fmt.Sprintf(" list %s", list.Title)
l.app.UI.StatusView.SetText(text)
l.app.UI.StatusView.SetControls("")
}
func (l *ListFeed) GetSavedIndex() int {
return l.index
}
func (l *ListFeed) Input(event *tcell.EventKey) {
index := l.GetSavedIndex()
if index > len(l.lists)-1 || len(l.lists) == 0 {
return
}
list := l.lists[index]
li := ListInfo{
name: list.Title,
id: list.ID,
}
controls := []ControlItem{ControlEnter, ControlList}
options := inputOptions(controls)
inputSimple(l.app, event, options, mastodon.Account{}, nil, nil, nil, nil, &li)
}

2
linkoverlay.go

@ -122,7 +122,7 @@ func (l *LinkOverlay) CopyToClipboard() {
text := l.GetURL()
if text != "" {
e := copyToClipboard(text)
if e == false {
if !e {
l.app.UI.CmdBar.ShowError("Couldn't copy to clipboard.")
}
}

6
main.go

@ -9,7 +9,7 @@ import (
"github.com/gdamore/tcell/v2"
)
const version string = "0.0.31"
const version string = "0.0.32"
func main() {
newUser := false
@ -131,7 +131,7 @@ func main() {
found = true
}
}
if found == false {
if !found {
log.Fatalf("Couldn't find a user named %s. Try again", selectedUser)
}
} else {
@ -296,7 +296,7 @@ func main() {
)
app.UI.CmdBar.Input.SetAutocompleteFunc(func(currentText string) (entries []string) {
words := strings.Split(":blocking,:boosts,:bookmarks,:compose,:favorites,:favorited,:muting,:profile,:saved,:tag,:timeline,:tl,:user,:quit,:q", ",")
words := strings.Split(":blocking,:boosts,:bookmarks,:compose,:favorites,:favorited,:lists,:muting,:profile,:saved,:tag,:timeline,:tl,:user,:quit,:q", ",")
if currentText == "" {
return
}

17
notifications.go

@ -5,6 +5,7 @@ import "github.com/rivo/tview"
type NotificationView struct {
app *App
list *tview.List
iconList *tview.List
feed Feed
loadingNewer bool
loadingOlder bool
@ -25,15 +26,25 @@ func NewNotificationView(app *App) *NotificationView {
nv.list.ShowSecondaryText(false)
nv.list.SetHighlightFullLine(true)
nv.iconList = tview.NewList()
nv.iconList.SetMainTextColor(app.Config.Style.Text)
nv.iconList.SetBackgroundColor(app.Config.Style.Background)
nv.iconList.SetSelectedTextColor(app.Config.Style.StatusBarViewText)
nv.iconList.SetSelectedBackgroundColor(app.Config.Style.StatusBarViewBackground)
nv.iconList.ShowSecondaryText(false)
nv.iconList.SetHighlightFullLine(true)
nv.feed = NewNotificationFeed(app, true)
return nv
}
func (n *NotificationView) SetList(items <-chan string) {
func (n *NotificationView) SetList(items <-chan ListItem) {
n.list.Clear()
n.iconList.Clear()
for s := range items {
n.list.AddItem(s, "", 0, nil)
n.list.AddItem(s.Text, "", 0, nil)
n.iconList.AddItem(s.Icons, "", 0, nil)
}
}
@ -54,6 +65,7 @@ func (n *NotificationView) loadNewer() {
newIndex := index + new
n.list.SetCurrentItem(newIndex)
n.iconList.SetCurrentItem(newIndex)
n.loadingNewer = false
})
}()
@ -74,6 +86,7 @@ func (n *NotificationView) loadOlder() {
index := n.list.GetCurrentItem()
n.feed.DrawList()
n.list.SetCurrentItem(index)
n.iconList.SetCurrentItem(index)
n.loadingOlder = false
})
}()

86
statusview.go

@ -13,6 +13,7 @@ func NewStatusView(app *App, tl TimelineType) *StatusView {
t := &StatusView{
app: app,
list: tview.NewList(),
iconList: tview.NewList(),
text: tview.NewTextView(),
controls: tview.NewTextView(),
focus: LeftPaneFocus,
@ -36,6 +37,13 @@ func NewStatusView(app *App, tl TimelineType) *StatusView {
t.list.ShowSecondaryText(false)
t.list.SetHighlightFullLine(true)
t.iconList.SetMainTextColor(app.Config.Style.Text)
t.iconList.SetBackgroundColor(app.Config.Style.Background)
t.iconList.SetSelectedTextColor(app.Config.Style.ListSelectedText)
t.iconList.SetSelectedBackgroundColor(app.Config.Style.ListSelectedBackground)
t.iconList.ShowSecondaryText(false)
t.iconList.SetHighlightFullLine(true)
t.text.SetWordWrap(true).SetDynamicColors(true)
t.text.SetBackgroundColor(app.Config.Style.Background)
t.text.SetTextColor(app.Config.Style.Text)
@ -46,22 +54,17 @@ func NewStatusView(app *App, tl TimelineType) *StatusView {
go func() {
d := time.Second * time.Duration(app.Config.General.AutoLoadSeconds)
ticker := time.NewTicker(d)
for {
select {
case <-ticker.C:
t.loadNewer()
}
for range ticker.C {
t.loadNewer()
}
}()
if app.Config.General.NotificationFeed {
go func() {
d := time.Second * time.Duration(app.Config.General.AutoLoadSeconds)
ticker := time.NewTicker(d)
for {
select {
case <-ticker.C:
t.notificationView.loadNewer()
}
for range ticker.C {
t.notificationView.loadNewer()
}
}()
}
@ -69,9 +72,15 @@ func NewStatusView(app *App, tl TimelineType) *StatusView {
return t
}
type ListItem struct {
Text string
Icons string
}
type StatusView struct {
app *App
list *tview.List
iconList *tview.List
flex *tview.Flex
text *tview.TextView
controls *tview.TextView
@ -89,6 +98,7 @@ func (t *StatusView) AddFeed(f Feed) {
t.feedIndex = len(t.feeds) - 1
f.DrawList()
t.list.SetCurrentItem(f.GetSavedIndex())
t.iconList.SetCurrentItem(f.GetSavedIndex())
f.DrawToot()
t.drawDesc()
@ -105,6 +115,7 @@ func (t *StatusView) CycleDraw() {
feed := t.feeds[t.feedIndex]
feed.DrawList()
t.list.SetCurrentItem(feed.GetSavedIndex())
t.iconList.SetCurrentItem(feed.GetSavedIndex())
if t.lastList == NotificationPaneFocus {
t.app.UI.SetFocus(NotificationPaneFocus)
@ -148,6 +159,7 @@ func (t *StatusView) RemoveCurrentFeed() {
feed := t.feeds[t.feedIndex]
feed.DrawList()
t.list.SetCurrentItem(feed.GetSavedIndex())
t.iconList.SetCurrentItem(feed.GetSavedIndex())
if t.lastList == NotificationPaneFocus {
t.app.UI.SetFocus(NotificationPaneFocus)
@ -170,13 +182,27 @@ func (t *StatusView) GetLeftView() tview.Primitive {
feed.DrawList()
feed.DrawToot()
}
return t.list
iw := 3
if !t.app.Config.General.ShowIcons {
iw = 0
}
v := tview.NewFlex().SetDirection(tview.FlexColumn).
AddItem(t.list, 0, 1, false).
AddItem(t.iconList, iw, 0, false)
return v
}
func (t *StatusView) GetNotificationView() tview.Primitive {
iw := 3
if !t.app.Config.General.ShowIcons {
iw = 0
}
if t.notificationView != nil {
t.notificationView.feed.DrawList()
return t.notificationView.list
v := tview.NewFlex().SetDirection(tview.FlexColumn).
AddItem(t.notificationView.list, 0, 1, false).
AddItem(t.notificationView.iconList, iw, 0, false)
return v
}
return nil
}
@ -351,10 +377,12 @@ func (t *StatusView) Input(event *tcell.EventKey) *tcell.EventKey {
return event
}
func (t *StatusView) SetList(items <-chan string) {
func (t *StatusView) SetList(items <-chan ListItem) {
t.list.Clear()
t.iconList.Clear()
for s := range items {
t.list.AddItem(s, "", 0, nil)
t.list.AddItem(s.Text, "", 0, nil)
t.iconList.AddItem(s.Icons, "", 0, nil)
}
}
func (t *StatusView) SetText(text string) {
@ -381,14 +409,17 @@ func (t *StatusView) drawDesc() {
func (t *StatusView) prev() {
var current int
var list *tview.List
var iList *tview.List
var feed Feed
if t.app.UI.Focus == LeftPaneFocus {
current = t.GetCurrentItem()
list = t.list
iList = t.iconList
feed = t.feeds[t.feedIndex]
} else {
current = t.notificationView.list.GetCurrentItem()
list = t.notificationView.list
iList = t.notificationView.iconList
feed = t.notificationView.feed
}
@ -396,6 +427,7 @@ func (t *StatusView) prev() {
current--
}
list.SetCurrentItem(current)
iList.SetCurrentItem(current)
feed.DrawToot()
if current < 4 {
@ -410,18 +442,20 @@ func (t *StatusView) prev() {
func (t *StatusView) next() {
var list *tview.List
var iList *tview.List
var feed Feed
if t.app.UI.Focus == LeftPaneFocus {
list = t.list
iList = t.iconList
feed = t.feeds[t.feedIndex]
} else {
list = t.notificationView.list
iList = t.notificationView.iconList
feed = t.notificationView.feed
}
list.SetCurrentItem(
list.GetCurrentItem() + 1,
)
list.SetCurrentItem(list.GetCurrentItem() + 1)
iList.SetCurrentItem(iList.GetCurrentItem() + 1)
feed.DrawToot()
count := list.GetItemCount()
@ -438,18 +472,22 @@ func (t *StatusView) next() {
func (t *StatusView) pgdown() {
var list *tview.List
var iList *tview.List
var feed Feed
if t.app.UI.Focus == LeftPaneFocus {
list = t.list
iList = t.iconList
feed = t.feeds[t.feedIndex]
} else {
list = t.notificationView.list
iList = t.notificationView.iconList
feed = t.notificationView.feed
}
_, _, _, height := list.GetInnerRect()
i := list.GetCurrentItem() + height - 1
list.SetCurrentItem(i)
iList.SetCurrentItem(i)
feed.DrawToot()
count := list.GetItemCount()
@ -466,12 +504,15 @@ func (t *StatusView) pgdown() {
func (t *StatusView) pgup() {
var list *tview.List
var iList *tview.List
var feed Feed
if t.app.UI.Focus == LeftPaneFocus {
list = t.list
iList = t.iconList
feed = t.feeds[t.feedIndex]
} else {
list = t.notificationView.list
iList = t.notificationView.iconList
feed = t.notificationView.feed
}
@ -481,6 +522,7 @@ func (t *StatusView) pgup() {
i = 0
}
list.SetCurrentItem(i)
iList.SetCurrentItem(i)
feed.DrawToot()
current := list.GetCurrentItem()
@ -501,16 +543,20 @@ func (t *StatusView) home() {
}
var list *tview.List
var iList *tview.List
var feed Feed
if t.app.UI.Focus == LeftPaneFocus {
list = t.list
iList = t.iconList
feed = t.feeds[t.feedIndex]
} else {
list = t.notificationView.list
iList = t.notificationView.iconList
feed = t.notificationView.feed
}
list.SetCurrentItem(0)
iList.SetCurrentItem(0)
feed.DrawToot()
switch t.app.UI.Focus {
@ -528,16 +574,20 @@ func (t *StatusView) end() {
}
var list *tview.List
var iList *tview.List
var feed Feed
if t.app.UI.Focus == LeftPaneFocus {
list = t.list
iList = t.iconList
feed = t.feeds[t.feedIndex]
} else {
list = t.notificationView.list
iList = t.notificationView.iconList
feed = t.notificationView.feed
}
list.SetCurrentItem(-1)
iList.SetCurrentItem(-1)
feed.DrawToot()
switch t.app.UI.Focus {
@ -568,6 +618,7 @@ func (t *StatusView) loadNewer() {
newIndex = 0
}
t.list.SetCurrentItem(newIndex)
t.iconList.SetCurrentItem(newIndex)
t.loadingNewer = false
})
}()
@ -589,6 +640,7 @@ func (t *StatusView) loadOlder() {
index := t.list.GetCurrentItem()
t.feeds[feedIndex].DrawList()
t.list.SetCurrentItem(index)
t.iconList.SetCurrentItem(index)
t.loadingOlder = false
})
}()

27
ui.go

@ -229,6 +229,19 @@ func (ui *UI) SetFocus(f FocusAt) {
ui.StatusView.list.SetSelectedTextColor(
ui.app.Config.Style.StatusBarViewText,
)
ui.StatusView.notificationView.iconList.SetSelectedBackgroundColor(
ui.app.Config.Style.ListSelectedBackground,
)
ui.StatusView.notificationView.iconList.SetSelectedTextColor(
ui.app.Config.Style.ListSelectedText,
)
ui.StatusView.iconList.SetSelectedBackgroundColor(
ui.app.Config.Style.StatusBarViewBackground,
)
ui.StatusView.iconList.SetSelectedTextColor(
ui.app.Config.Style.StatusBarViewText,
)
default:
ui.app.UI.StatusBar.Text.SetBackgroundColor(
ui.app.Config.Style.StatusBarBackground,
@ -242,6 +255,12 @@ func (ui *UI) SetFocus(f FocusAt) {
ui.StatusView.list.SetSelectedTextColor(
ui.app.Config.Style.ListSelectedText,
)
ui.StatusView.iconList.SetSelectedBackgroundColor(
ui.app.Config.Style.ListSelectedBackground,
)
ui.StatusView.iconList.SetSelectedTextColor(
ui.app.Config.Style.ListSelectedText,
)
if ui.app.Config.General.NotificationFeed {
ui.StatusView.notificationView.list.SetSelectedBackgroundColor(
@ -250,6 +269,12 @@ func (ui *UI) SetFocus(f FocusAt) {
ui.StatusView.notificationView.list.SetSelectedTextColor(
ui.app.Config.Style.StatusBarViewText,
)
ui.StatusView.notificationView.iconList.SetSelectedBackgroundColor(
ui.app.Config.Style.StatusBarViewBackground,
)
ui.StatusView.notificationView.iconList.SetSelectedTextColor(
ui.app.Config.Style.StatusBarViewText,
)
}
ui.Pages.SwitchToPage("main")
ui.FocusAt(nil, "-- LIST --")
@ -445,7 +470,7 @@ func (ui *UI) LoggedIn() {
}
ui.app.Me = me
ui.StatusView.AddFeed(
NewTimelineFeed(ui.app, ui.Timeline),
NewTimelineFeed(ui.app, ui.Timeline, nil),
)
}

14
util.go

@ -48,7 +48,7 @@ func getURLs(text string) []URL {
case html.StartTagToken:
token := doc.Token()
if "a" == token.Data {
if token.Data == "a" {
url := URL{}
var appendUrl = true
for _, a := range token.Attr {
@ -380,27 +380,27 @@ func OutputDate(status time.Time, today time.Time, long, short string, relativeD
func Notify(nc NotificationConfig, t NotificationType, title string, body string) {
switch t {
case NotificationFollower:
if nc.NotificationFollower == false {
if !nc.NotificationFollower {
return
}
case NotificationFavorite:
if nc.NotificationFavorite == false {
if !nc.NotificationFavorite {
return
}
case NotificationMention:
if nc.NotificationMention == false {
if !nc.NotificationMention {
return
}
case NotificationBoost:
if nc.NotificationBoost == false {
if !nc.NotificationBoost {
return
}
case NotificationPoll:
if nc.NotificationPoll == false {
if !nc.NotificationPoll {
return
}
case NotificationPost:
if nc.NotificationPost == false {
if !nc.NotificationPost {
return
}
default:

Loading…
Cancel
Save