You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cointop/cointop/table.go

265 lines
5.9 KiB
Go

package cointop
import (
"fmt"
"net/url"
"strings"
"github.com/miguelmota/cointop/pkg/ui"
)
// TableView is structure for table view
type TableView = ui.View
// NewTableView returns a new table view
func NewTableView() *TableView {
var view *TableView = ui.NewView("table")
return view
}
// TableColumnOrder returns the default order of the table columns
func TableColumnOrder() []string {
return []string{
"rank",
"name",
"symbol",
"price",
"holdings",
"balance",
"market_cap",
"24h_volume",
"1h_change",
"7d_change",
"total_supply",
"available_supply",
"percent_holdings",
"last_updated",
}
}
const dots = "..."
// RefreshTable refreshes the table
func (ct *Cointop) RefreshTable() error {
ct.debuglog("refreshTable()")
switch ct.State.selectedView {
case PortfolioView:
ct.table = ct.GetPortfolioTable()
case PriceAlertsView:
ct.table = ct.GetPriceAlertsTable()
default:
ct.table = ct.GetCoinsTable()
}
ct.table.HideColumHeaders = true
// highlight last row if current row is out of bounds (can happen when switching views)
currentrow := ct.HighlightedRowIndex()
if len(ct.State.coins) > currentrow {
ct.HighlightRow(currentrow)
}
ct.UpdateUI(func() error {
ct.Views.Table.Clear()
ct.table.Format().Fprint(ct.Views.Table.Backing())
go ct.RowChanged()
go ct.UpdateTableHeader()
go ct.UpdateMarketbar()
go ct.UpdateChart()
return nil
})
return nil
}
// UpdateTable updates the table
func (ct *Cointop) UpdateTable() error {
ct.debuglog("UpdateTable()")
ct.State.allCoinsSlugMap.Range(func(key, value interface{}) bool {
k := key.(string)
if v, ok := value.(*Coin); ok {
v.Favorite = ct.State.favorites[v.Name]
ct.State.allCoinsSlugMap.Store(k, v)
}
return true
})
if ct.IsFavoritesVisible() {
ct.State.coins = ct.GetFavoritesSlice()
} else if ct.IsPortfolioVisible() {
ct.State.coins = ct.GetPortfolioSlice()
} else {
// TODO: maintain state of previous sorting
if ct.State.sortBy == "holdings" {
ct.State.sortBy = "rank"
ct.State.sortDesc = false
}
ct.State.coins = ct.GetTableCoinsSlice()
}
ct.Sort(ct.State.sortBy, ct.State.sortDesc, ct.State.coins, true)
go ct.RefreshTable()
return nil
}
// GetTableCoinsSlice returns a slice of the table rows
func (ct *Cointop) GetTableCoinsSlice() []*Coin {
ct.debuglog("GetTableCoinsSlice()")
sliced := []*Coin{}
start := ct.State.page * ct.State.perPage
end := start + ct.State.perPage
allCoins := ct.AllCoins()
size := len(allCoins)
if start < 0 {
start = 0
}
if end >= size-1 {
start = int(float64(start/100) * 100)
end = size - 1
}
if start < 0 {
start = 0
}
if end >= size {
end = size - 1
}
if end < 0 {
end = 0
}
if start >= end {
return nil
}
if end > 0 {
sliced = allCoins[start:end]
// NOTE: restore rank
for _, coin := range sliced {
icoin, _ := ct.State.allCoinsSlugMap.Load(coin.Name)
if icoin != nil {
c, _ := icoin.(*Coin)
coin.Rank = c.Rank
}
}
}
return sliced
}
// HighlightedRowIndex returns the index of the highlighted row
func (ct *Cointop) HighlightedRowIndex() int {
ct.debuglog("HighlightedRowIndex()")
oy := ct.Views.Table.OriginY()
cy := ct.Views.Table.CursorY()
idx := oy + cy
if idx < 0 {
idx = 0
}
if idx >= len(ct.State.coins) {
idx = len(ct.State.coins) - 1
}
return idx
}
// HighlightedRowCoin returns the coin at the index of the highlighted row
func (ct *Cointop) HighlightedRowCoin() *Coin {
ct.debuglog("HighlightedRowCoin()")
idx := ct.HighlightedRowIndex()
if len(ct.State.coins) == 0 {
return nil
}
return ct.State.coins[idx]
}
// HighlightedPageRowIndex returns the index of page row of the highlighted row
func (ct *Cointop) HighlightedPageRowIndex() int {
ct.debuglog("HighlightedPageRowIndex()")
cy := ct.Views.Table.CursorY()
idx := cy
if idx < 0 {
idx = 0
}
return idx
}
// RowLink returns the row url link
func (ct *Cointop) RowLink() string {
ct.debuglog("RowLink()")
coin := ct.HighlightedRowCoin()
if coin == nil {
return ""
}
return ct.api.CoinLink(coin.Name)
}
// RowLinkShort returns a shortened version of the row url link
func (ct *Cointop) RowLinkShort() string {
ct.debuglog("RowLinkShort()")
link := ct.RowLink()
if link != "" {
u, err := url.Parse(link)
if err != nil {
return ""
}
host := u.Hostname()
host = strings.Replace(host, "www.", "", -1)
path := u.EscapedPath()
parts := strings.Split(path, "/")
if len(parts) > 0 {
path = parts[len(parts)-1]
}
return fmt.Sprintf("http://%s/%s/%s", host, dots, path)
}
return ""
}
// ToggleTableFullscreen toggles the table fullscreen mode
func (ct *Cointop) ToggleTableFullscreen() error {
ct.debuglog("ToggleTableFullscreen()")
ct.State.onlyTable = !ct.State.onlyTable
if !ct.State.onlyTable {
// NOTE: cached values are initial config settings.
// If the only-table config was set then toggle
// all other initial hidden views.
onlyTable, _ := ct.cache.Get("onlyTable")
if onlyTable.(bool) {
ct.State.hideMarketbar = false
ct.State.hideChart = false
ct.State.hideStatusbar = false
} else {
// NOTE: cached values store initial hidden views preferences.
hideMarketbar, _ := ct.cache.Get("hideMarketbar")
ct.State.hideMarketbar = hideMarketbar.(bool)
hideChart, _ := ct.cache.Get("hideChart")
ct.State.hideChart = hideChart.(bool)
hideStatusbar, _ := ct.cache.Get("hideStatusbar")
ct.State.hideStatusbar = hideStatusbar.(bool)
}
}
return nil
}
// SetSelectedView sets the active table view
func (ct *Cointop) SetSelectedView(viewName string) {
ct.State.lastSelectedView = ct.State.selectedView
ct.State.selectedView = viewName
}
// ToggleSelectedView toggles between current table view and last selected table view
func (ct *Cointop) ToggleSelectedView(viewName string) {
if ct.State.lastSelectedView == "" || ct.State.selectedView != viewName {
ct.SetSelectedView(viewName)
} else {
ct.SetSelectedView(ct.State.lastSelectedView)
}
}