From 5e2134e43e215b2c09ef8c6b8e8113c42d55d2c5 Mon Sep 17 00:00:00 2001 From: Miguel Mota Date: Sun, 8 Sep 2019 09:48:20 -0700 Subject: [PATCH] Fix sorting issue with favorites and portfolio --- README.md | 8 +++-- cointop/cointop.go | 3 +- cointop/favorites.go | 19 ++++++++++ cointop/navigation.go | 12 +++++++ cointop/portfolio.go | 16 ++++++++- cointop/save.go | 4 +++ cointop/sort.go | 2 ++ cointop/table.go | 83 ++++++++++++++++++++++--------------------- cointop/update.go | 6 ++++ 9 files changed, 108 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index b8d683b..9fc2286 100644 --- a/README.md +++ b/README.md @@ -684,7 +684,7 @@ Frequently asked questions: - Q: How do I save my favorites? - - A: Press ctrl+s to save your favorites. + - A: Favorites are autosaved when setting them. You can also press ctrl+s to manually save your favorites to the config file. - Q: What does the yellow asterisk in the row mean? @@ -710,6 +710,10 @@ Frequently asked questions: - A: Press P (Shift+p) to toggle view your portfolio. +- Q: How do I save my portfolio? + + - A: Your portfolio is autosaved after you edit holdings. You can also press ctrl+s to manually save your portfolio holdings to the config file. + - Q: I'm getting question marks or weird symbols instead of the correct characters. - A: Make sure that your terminal has the encoding set to UTF-8 and that your terminal font supports UTF-8. @@ -809,7 +813,7 @@ Frequently asked questions: - Q: How do I save the selected currency to convert to? - - A: Press ctrl+s to save the selected currency to convert to. + - A: The selected currency conversion is autosaved. You can also press ctrl+s to manually save the selected currency conversion. - Q: What does saving do? diff --git a/cointop/cointop.go b/cointop/cointop.go index b52d7d2..be075c6 100644 --- a/cointop/cointop.go +++ b/cointop/cointop.go @@ -57,6 +57,7 @@ type State struct { hideMarketbar bool hideChart bool hideStatusbar bool + lastSelectedRowIndex int page int perPage int portfolio *Portfolio @@ -340,8 +341,8 @@ func (ct *Cointop) Run() error { g.BgColor = ct.colorscheme.BaseBg() ct.g = g defer g.Close() - g.InputEsc = true + g.InputEsc = true g.Mouse = true g.Highlight = true g.SetManagerFunc(ct.layout) diff --git a/cointop/favorites.go b/cointop/favorites.go index 3cd88c0..e400dc3 100644 --- a/cointop/favorites.go +++ b/cointop/favorites.go @@ -6,6 +6,7 @@ func (ct *Cointop) toggleFavorite() error { if coin == nil { return nil } + _, ok := ct.State.favorites[coin.Name] if ok { delete(ct.State.favorites, coin.Name) @@ -14,7 +15,13 @@ func (ct *Cointop) toggleFavorite() error { ct.State.favorites[coin.Name] = true coin.Favorite = true } + go ct.updateTable() + + if err := ct.save(); err != nil { + return err + } + return nil } @@ -24,3 +31,15 @@ func (ct *Cointop) toggleShowFavorites() error { go ct.updateTable() return nil } + +func (ct *Cointop) getFavoritesSlice() []*Coin { + sliced := []*Coin{} + for i := range ct.State.allCoins { + coin := ct.State.allCoins[i] + if coin.Favorite { + sliced = append(sliced, coin) + } + } + + return sliced +} diff --git a/cointop/navigation.go b/cointop/navigation.go index df333e1..6e2546b 100644 --- a/cointop/navigation.go +++ b/cointop/navigation.go @@ -228,6 +228,18 @@ func (ct *Cointop) lastPage() error { return nil } +func (ct *Cointop) goToPageRowIndex(idx int) error { + if ct.Views.Table.Backing() == nil { + return nil + } + cx, _ := ct.Views.Table.Backing().Cursor() + if err := ct.Views.Table.Backing().SetCursor(cx, idx); err != nil { + return err + } + ct.rowChanged() + return nil +} + func (ct *Cointop) goToGlobalIndex(idx int) error { perpage := ct.totalPerPage() atpage := idx / perpage diff --git a/cointop/portfolio.go b/cointop/portfolio.go index bacb67c..ccd6513 100644 --- a/cointop/portfolio.go +++ b/cointop/portfolio.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/miguelmota/cointop/cointop/common/pad" + log "github.com/sirupsen/logrus" ) // PortfolioUpdateMenuView is structure for portfolio update menu view @@ -21,8 +22,15 @@ func NewPortfolioUpdateMenuView() *PortfolioUpdateMenuView { } func (ct *Cointop) togglePortfolio() error { + if ct.State.portfolioVisible { + ct.goToPageRowIndex(ct.State.lastSelectedRowIndex) + } else { + ct.State.lastSelectedRowIndex = ct.HighlightedPageRowIndex() + } + ct.State.filterByFavorites = false ct.State.portfolioVisible = !ct.State.portfolioVisible + go ct.UpdateChart() go ct.updateTable() return nil @@ -80,6 +88,7 @@ func (ct *Cointop) showPortfolioUpdateMenu() error { return nil } + ct.State.lastSelectedRowIndex = ct.HighlightedPageRowIndex() ct.State.portfolioUpdateMenuVisible = true ct.updatePortfolioUpdateMenu() ct.SetActiveView(ct.Views.PortfolioUpdateMenu.Name()) @@ -111,6 +120,7 @@ func (ct *Cointop) setPortfolioHoldings() error { defer ct.hidePortfolioUpdateMenu() coin := ct.HighlightedRowCoin() + // read input field b := make([]byte, 100) n, err := ct.Views.Input.Backing().Read(b) if n == 0 { @@ -136,7 +146,7 @@ func (ct *Cointop) setPortfolioHoldings() error { ct.goToGlobalIndex(0) } else { ct.updateTable() - ct.goToGlobalIndex(coin.Rank - 1) + ct.goToPageRowIndex(ct.State.lastSelectedRowIndex) } return nil @@ -181,6 +191,10 @@ func (ct *Cointop) setPortfolioEntry(coin string, holdings float64) { } else { p.Holdings = holdings } + + if err := ct.save(); err != nil { + log.Fatal(err) + } } func (ct *Cointop) removePortfolioEntry(coin string) { diff --git a/cointop/save.go b/cointop/save.go index 460331a..ac8f6a6 100644 --- a/cointop/save.go +++ b/cointop/save.go @@ -11,6 +11,10 @@ func (ct *Cointop) save() error { } func (ct *Cointop) setSavingStatus() { + if ct.g == nil { + return + } + go func() { ct.loadingTicks("saving", 590) ct.updateStatusbar("") diff --git a/cointop/sort.go b/cointop/sort.go index ef6a17b..57bb3a3 100644 --- a/cointop/sort.go +++ b/cointop/sort.go @@ -90,6 +90,7 @@ func (ct *Cointop) sortPrevCol() error { if k < 0 { k = 0 } + nextsortBy = ct.tableColumnOrder[k] ct.sort(nextsortBy, ct.State.sortDesc, ct.State.coins, true) ct.updateTable() @@ -104,6 +105,7 @@ func (ct *Cointop) sortNextCol() error { if k > l-1 { k = l - 1 } + nextsortBy = ct.tableColumnOrder[k] ct.sort(nextsortBy, ct.State.sortDesc, ct.State.coins, true) ct.updateTable() diff --git a/cointop/table.go b/cointop/table.go index 19ccceb..802be48 100644 --- a/cointop/table.go +++ b/cointop/table.go @@ -211,55 +211,45 @@ func (ct *Cointop) updateTable() error { ct.State.allCoinsSlugMap.Store(k, v) } } + return true }) if ct.State.filterByFavorites { - for i := range ct.State.allCoins { - coin := ct.State.allCoins[i] - if coin.Favorite { - sliced = append(sliced, coin) - } - } + sliced = ct.getFavoritesSlice() ct.State.coins = sliced - go ct.RefreshTable() - return nil - } - - if ct.State.portfolioVisible { + } else if ct.State.portfolioVisible { sliced = ct.getPortfolioSlice() ct.State.coins = sliced - go ct.RefreshTable() - return nil - } - - 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(math.Floor(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] + } else { + 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(math.Floor(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] + } + ct.State.coins = sliced } - ct.State.coins = sliced ct.sort(ct.State.sortBy, ct.State.sortDesc, ct.State.coins, true) go ct.RefreshTable() @@ -289,6 +279,17 @@ func (ct *Cointop) HighlightedRowCoin() *Coin { return ct.State.coins[idx] } +// HighlightedPageRowIndex returns the index of page row of the highlighted row +func (ct *Cointop) HighlightedPageRowIndex() int { + _, cy := ct.Views.Table.Backing().Cursor() + idx := cy + if idx < 0 { + idx = 0 + } + + return idx +} + // RowLink returns the row url link func (ct *Cointop) RowLink() string { coin := ct.HighlightedRowCoin() diff --git a/cointop/update.go b/cointop/update.go index 293205d..5a4c439 100644 --- a/cointop/update.go +++ b/cointop/update.go @@ -1,12 +1,18 @@ package cointop import ( + "sync" + "github.com/jroimartin/gocui" log "github.com/sirupsen/logrus" ) +var updateMutex sync.Mutex + // update takes a callback which updates the view func (ct *Cointop) update(f func()) { + updateMutex.Lock() + defer updateMutex.Unlock() if ct.g == nil { log.Fatal("gocui is not initialized") }