Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,7 @@ autoread: true
```

### Ordering

Set the default sort ordering of the list
Set the default sort ordering of the list. Ordering can be one of "asc", "desc" or "length". Length will sort by article content length in ascending order, unread items still show at the top.

```yaml
ordering: asc
Expand Down
7 changes: 5 additions & 2 deletions internal/commands/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,13 @@ func (m *model) UpdateList() tea.Cmd {
func sortList(m model) func() tea.Msg {
return func() tea.Msg {
// reverse sorting order
if m.commands.config.Ordering == constants.AscendingOrdering {
switch m.commands.config.Ordering {
case constants.AscendingOrdering:
m.commands.config.Ordering = constants.DescendingOrdering
} else {
case constants.DescendingOrdering:
m.commands.config.Ordering = constants.AscendingOrdering
default:
// noop
}

items, err := m.commands.GetAllFeeds()
Expand Down
1 change: 1 addition & 0 deletions internal/constants/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ package constants
const (
AscendingOrdering = "asc"
DescendingOrdering = "desc"
LengthOrdering = "length"
DefaultOrdering = AscendingOrdering
)
12 changes: 9 additions & 3 deletions internal/store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,15 +257,21 @@ func (sls *SQLiteStore) upsertItem(db statementPreparer, item *Item) error {
// TODO: pagination
func (sls SQLiteStore) GetAllItems(ordering string) ([]Item, error) {
itemStmt := `
select id, feedurl, guid, link, title, content, author, readat, favourite, publishedat, createdat, updatedat from items order by readat is not null asc, coalesce(publishedat, createdat) %s;
select id, feedurl, guid, link, title, content, author, readat, favourite, publishedat, createdat, updatedat from items order by readat is not null asc, %s;
`

var stmt string
var timeStmt string

switch ordering {
case constants.LengthOrdering:
stmt = fmt.Sprintf(itemStmt, "length(content) asc")
case constants.DescendingOrdering:
stmt = fmt.Sprintf(itemStmt, constants.DescendingOrdering)
timeStmt = fmt.Sprintf("coalesce(publishedat, createdat) %s", constants.DescendingOrdering)
stmt = fmt.Sprintf(itemStmt, timeStmt)
default:
stmt = fmt.Sprintf(itemStmt, constants.DefaultOrdering)
timeStmt = fmt.Sprintf("coalesce(publishedat, createdat) %s", constants.DefaultOrdering)
stmt = fmt.Sprintf(itemStmt, timeStmt)
}

rows, err := sls.db.Query(stmt)
Expand Down
107 changes: 107 additions & 0 deletions internal/store/store_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package store

import (
"testing"
"time"
)

func TestStore_GetAllItemsOrder(t *testing.T) {
now := time.Now()
testCases := []struct {
name string
ordering string
items []Item
expectedOrder []string
}{
{
name: "test descending_by_new",
ordering: "desc",
items: []Item{
{
PublishedAt: now.Add(-2 * time.Hour),
CreatedAt: now.Add(-2 * time.Hour),
Title: "First Item",
Content: "A short string",
FeedURL: "example.com",
Link: "example.com/endpoint",
},
{
PublishedAt: now.Add(-23 * time.Hour),
CreatedAt: now.Add(-24 * time.Hour),
Title: "Second Item",
Content: "A really long string",
FeedURL: "example.com",
Link: "example.com/api",
},
{
PublishedAt: now.Add(-20 * time.Hour),
CreatedAt: now.Add(-20 * time.Hour),
Title: "Third Item",
Content: "Some boring string. Use lorem ipsum",
FeedURL: "example.com",
Link: "example.com/anotherExample",
},
},
expectedOrder: []string{"First Item", "Second Item", "Third Item"},
},
{
name: "test_order_by_content_size",
ordering: "length",
items: []Item{
{
PublishedAt: now.Add(-2 * time.Hour),
CreatedAt: now.Add(-2 * time.Hour),
Title: "First Item",
Content: "AA",
FeedURL: "example.com",
Link: "example.com/endpoint",
},
{
PublishedAt: now.Add(-23 * time.Hour),
CreatedAt: now.Add(-24 * time.Hour),
Title: "Second Item",
Content: "AAA",
FeedURL: "example.com",
Link: "example.com/api",
},
{
PublishedAt: now.Add(-20 * time.Hour),
CreatedAt: now.Add(-20 * time.Hour),
Title: "Third Item",
Content: "A",
FeedURL: "example.com",
Link: "example.com/anotherExample",
},
},
expectedOrder: []string{"First Item", "Second Item", "Third Item"},
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
sls, err := NewInMemorySQLiteStore()
if err != nil {
t.Fatalf("Error initailizing db: %v", err)
}
for _, item := range tc.items {
err = sls.UpsertItem(&item)
if item.Title == "Third Item" {
sls.ToggleRead(item.ID)
}
if err != nil {
t.Errorf("Error insert %v: %v", item, err)
}
}
allItems, err := sls.GetAllItems(tc.ordering)
if err != nil {
t.Fatalf("Error fetching all items: %v", err)
}
for i := range allItems {
if allItems[i].Title != tc.expectedOrder[i] {
t.Fatalf("Unexpected item order. Want: %v Got: %v", tc.expectedOrder[i], allItems[i].Title)
}
}

})
}
}
Loading