3 files changed,
66 insertions(+),
26 deletions(-)
Author:
Oleksandr Smirnov
olexsmir@gmail.com
Committed at:
2025-12-28 19:20:24 +0200
Change ID:
wwrttonpnutrzrnzppoxmntsrsukuloo
Parent:
47b0d33
M
internal/store/sqlite_articles.go
@@ -56,6 +56,14 @@ _, err := s.db.ExecContext(ctx, query, args...)
return err } +type ArticleKind int + +const ( + ArticleStarred ArticleKind = iota + ArticleUnread + ArticleAll +) + type Article struct { ID string Title string@@ -69,14 +77,20 @@ FeedTitle string
PublishedAt int64 } -func (s *Sqlite) GetArticles(ctx context.Context) ([]Article, error) { - query := `--sql +var getArticlesWhereClause = map[ArticleKind]string{ + ArticleAll: "", + ArticleStarred: "where s.is_starred = true", + ArticleUnread: "where s.is_read = false", +} + +func (s *Sqlite) GetArticles(ctx context.Context, kind ArticleKind) ([]Article, error) { + query := fmt.Sprintf(`--sql select a.id, a.title, a.href, a.content, a.author, s.is_read, s.is_starred, a.feed_id, f.title feed_name, a.published_at from articles a join article_statuses s on a.id = s.article_id join feeds f on f.id = a.feed_id - where s.is_read = false - order by a.published_at desc` + %s + order by a.published_at desc`, getArticlesWhereClause[kind]) rows, err := s.db.QueryContext(ctx, query) if err != nil {
M
internal/tui/fetcher.go
@@ -1,18 +1,61 @@
package tui import ( + "time" + + "github.com/charmbracelet/bubbles/table" tea "github.com/charmbracelet/bubbletea" "olexsmir.xyz/smutok/internal/store" ) type fetchedArticles []store.Article -func (m *Model) fetchArticles() tea.Cmd { +func (m *Model) fetchArticles(kind store.ArticleKind) tea.Cmd { return func() tea.Msg { - articles, err := m.store.GetArticles(m.ctx) + articles, err := m.store.GetArticles(m.ctx, kind) if err != nil { return sendErr(err) } return fetchedArticles(articles) } } + +func (m *Model) setupTableWithArticles() { + // clean up previous state + m.table.SetRows([]table.Row{}) + + columns := []table.Column{ + {Title: "date", Width: 10}, + {Title: "status", Width: 6}, + {Title: "author", Width: 14}, + {Title: "title", Width: m.table.Width() - 30}, + } + + rows := make([]table.Row, len(m.articles)) + for i, a := range m.articles { + rows[i] = table.Row{ + m.toArticleDate(a.PublishedAt), + m.toArticleStatus(a.IsRead, a.IsStarred), + a.Author, + a.Title, + } + } + + m.table.SetColumns(columns) + m.table.SetRows(rows) +} + +func (m *Model) toArticleStatus(isRead, isStarred bool) string { + var out string + if isRead { + out += "✓ " + } + if isStarred { + out += "★ " + } + return out +} + +func (m *Model) toArticleDate(publishedAt int64) string { + return time.Unix(publishedAt, 0).Format("2006/01/02") +}
M
internal/tui/tui.go
@@ -2,7 +2,6 @@ package tui
import ( "context" - "log/slog" "github.com/charmbracelet/bubbles/table" "github.com/charmbracelet/bubbles/viewport"@@ -67,7 +66,7 @@
func (m *Model) Init() tea.Cmd { return tea.Batch( tea.SetWindowTitle("smutok"), - m.fetchArticles(), + m.fetchArticles(store.ArticleAll), ) }@@ -81,30 +80,14 @@ return m, nil
case tea.WindowSizeMsg: m.table.SetHeight(msg.Height) - m.table.SetWidth(msg.Width) + m.table.SetWidth(msg.Width - 2) m.viewport.Height = msg.Height m.viewport.Width = msg.Width return m, nil case fetchedArticles: m.articles = msg - - columns := []table.Column{ - // {Title: "read", Width: 4}, - // {Title: "stared", Width: 6}, - {Title: "author", Width: 14}, - {Title: "title", Width: m.table.Width() - 14}, - } - - rows := make([]table.Row, len(msg)) - for i, article := range msg { - rows[i] = table.Row{article.Author, article.Title} - } - - m.table.SetColumns(columns) - m.table.SetRows(rows) - - slog.Debug("got articles") + m.setupTableWithArticles() return m, nil case tea.KeyMsg: