shithub: hell

ref: e6cb144f4f91ed3b287e8f0217cb8084a04afc7d
dir: /pages.go/

View raw version
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 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
}

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

	statuses, err := statusData.getter.Get(limit)
	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
		}
		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]

	reverseditems := reverseArray(items)
	for i, _ := range reverseditems {
		sb.WriteString(reverseditems[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
}