ref: 16fd80edde8e3928854f8e600c5037459b97163d
dir: /pages.go/
package main
import (
"context"
"fmt"
"strings"
"codeberg.org/penny64/hellclient-go-mastodon"
"golang.org/x/term"
)
type StatusLoader interface {
Load(int) *[]PageItem
}
type StatusGetter interface {
Get(int) ([]*mastodon.Status, error)
}
type BasicStatusGetter struct {
getter func(ctx context.Context, pg *mastodon.Pagination) ([]*mastodon.Status, error)
page *mastodon.Pagination
}
type ThreadStatusGetter struct {
target *mastodon.Status
client *mastodon.Client
loaded bool
}
// The API doesn't take a limit for this so we ignore the limit
func (getter *ThreadStatusGetter) Get(limit int) ([]*mastodon.Status, error) {
if getter.loaded {
return nil, nil
}
context, err := getter.client.GetStatusContext(context.Background(), getter.target.ID)
if err == nil {
getter.loaded = true
}
var statuses []*mastodon.Status
for _, post := range context.Ancestors {
statuses = append(statuses, post)
}
statuses = append(statuses, getter.target)
for _, post := range context.Descendants {
statuses = append(statuses, post)
}
return statuses, err
}
func (getter *BasicStatusGetter) Get(limit int) ([]*mastodon.Status, error) {
if getter.page == nil {
getter.page = &mastodon.Pagination{}
}
getter.page.Limit = int64(limit)
statuses, err := getter.getter(context.Background(), getter.page)
getter.page.MinID = ""
return statuses, err
}
type AccountStatusGetter struct {
page *mastodon.Pagination
ID mastodon.ID
client *mastodon.Client
}
func (getter *AccountStatusGetter) Get(limit int) ([]*mastodon.Status, error) {
if getter.page == nil {
getter.page = &mastodon.Pagination{}
}
getter.page.Limit = int64(limit)
statuses, err := getter.client.GetAccountStatuses(context.Background(), getter.ID, getter.page)
getter.page.MinID = ""
return statuses, err
}
type Page struct {
loader StatusLoader
//Array index for the item buffer
index int
//Index of the last item on the page
indexend int
//our previous index for going back
previndexes []int
//Semantic page number for the UI
page int
//don't flip the order around
disablereverse bool
itembuffer *[]PageItem
}
type NotificationPages struct {
hc *Hellclient
page *mastodon.Pagination
}
type StatusPages struct {
hc *Hellclient
prefix string
getter StatusGetter
}
type PageItem struct {
itemtext string
lines int
}
func makePageItem(renderedtext string) (page PageItem) {
page.lines = strings.Count(renderedtext, "\n")
page.itemtext = renderedtext
return
}
func (statusData *StatusPages) Load(limit int) *[]PageItem {
var itemArray []PageItem
var statuses []*mastodon.Status
var err error
statusfunc := func(job *GenericJob) { statuses, err = statusData.getter.Get(limit) }
statusjob := statusData.hc.dispatchFunc(statusfunc)
statusjob.Wait()
if err != nil {
fmt.Printf("Couldn't load status page: %s\n", err)
}
for i, _ := range statuses {
item := makePageItem(statusData.hc.renderAndIncrement(statusData.hc.ctxref, statuses[i]) + "\n")
itemArray = append(itemArray, item)
}
return &itemArray
}
func (noticeData *NotificationPages) Load(limit int) *[]PageItem {
if noticeData.page == nil {
noticeData.page = &mastodon.Pagination{}
}
noticeData.page.Limit = int64(limit)
var notices []*mastodon.Notification
var err error
getnotifs := func(job *GenericJob) {
notices, err = noticeData.hc.client.GetNotifications(context.Background(), noticeData.page)
}
notifjob := noticeData.hc.dispatchFunc(getnotifs)
notifjob.Wait()
if err != nil {
fmt.Printf("Error getting notification page: %s\n", err)
}
noticeArray := noticeData.hc.RenderNotificationsArray(notices)
var itemArray []PageItem
for i, _ := range noticeArray {
item := makePageItem(noticeArray[i] + "\n")
itemArray = append(itemArray, item)
}
noticeData.page.MinID = ""
return &itemArray
}
func findIndex(height int, items []PageItem) (index int) {
linecount := 5
for i, _ := range items {
linecount = linecount + items[i].lines
if i != 0 && linecount > height {
return
}
//-1 lines indicates we should display this item on its own page
if i != 0 && items[i].lines == -1 {
return
}
if i == 0 && items[i].lines == -1 {
index++
return
}
index++
}
return
}
func (page *Page) findIndexStart() {
_, windowheight, err := term.GetSize(int(0))
if err != nil {
//Not a tty? Dunno, here's 25 lines for a standard terminal
windowheight = 25
}
var items []PageItem
items = (*page.itembuffer)[:page.index]
items = reverseArray(items)
page.index = page.index - findIndex(windowheight, items)
return
}
func (page *Page) findIndexEnd() {
_, windowheight, err := term.GetSize(int(0))
if err != nil {
//Not a tty? Dunno, here's 25 lines for a standard terminal
windowheight = 25
}
page.indexend = page.index
var items []PageItem
if len(*page.itembuffer) >= page.index {
items = (*page.itembuffer)[page.index:]
page.indexend = page.indexend + findIndex(windowheight, items)
}
return
}
func (page *Page) Buffer() {
if page.itembuffer == nil {
page.itembuffer = &[]PageItem{}
}
if page.indexend == 0 {
*page.itembuffer = append(*page.itembuffer, *page.loader.Load(20)...)
}
if len(*page.itembuffer) < page.indexend {
*page.itembuffer = append(*page.itembuffer, *page.loader.Load(20)...)
}
}
func (page *Page) String() string {
var sb strings.Builder
page.Buffer()
page.findIndexEnd()
var items []PageItem
items = (*page.itembuffer)[page.index:page.indexend]
if !page.disablereverse {
items = reverseArray(items)
}
for i, _ := range items {
sb.WriteString(items[i].itemtext)
}
sb.WriteString(page.pageTitle())
return sb.String()
}
func (page *Page) Next() {
page.page++
page.index = page.indexend
page.indexend = 0
page.Buffer()
page.findIndexEnd()
}
func (page *Page) Prev() {
page.findIndexStart()
if page.page > 0 {
page.page--
}
}
func (page *Page) pageTitle() string {
return fmt.Sprintf("Page %v. /next for next page /prev for previous\n", page.page+1)
}
func (page *Page) Current() int {
return page.page
}