107 lines
2.5 KiB
Go
107 lines
2.5 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"slices"
|
|
"time"
|
|
|
|
"github.com/charmbracelet/bubbles/list"
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
"github.com/simonhege/timeago"
|
|
miniflux "miniflux.app/client"
|
|
)
|
|
|
|
type feedEntry struct {
|
|
ID int64
|
|
Name string
|
|
Feed string
|
|
Link string
|
|
PublishedAt time.Time
|
|
}
|
|
|
|
func (fe feedEntry) Title() string { return fe.Name }
|
|
func (fe feedEntry) Description() string {
|
|
formattedTimeAgo := timeago.WithMax(timeago.English, time.Hour*7*24, timeago.English.DefaultLayout).Format(fe.PublishedAt)
|
|
return fmt.Sprintf("%s - Published %s", fe.Feed, formattedTimeAgo)
|
|
}
|
|
func (fe feedEntry) FilterValue() string { return fmt.Sprintf("%s - %s", fe.Name, fe.Feed) }
|
|
|
|
type feedEntriesModel struct {
|
|
minifluxClient *miniflux.Client
|
|
entries list.Model
|
|
selectedEntry *feedEntry
|
|
}
|
|
|
|
type MsgFetchedEntries []feedEntry
|
|
type MsgFetchedEntriesError error
|
|
|
|
func (m *feedEntriesModel) fetchEntries() tea.Msg {
|
|
entriesResult, err := m.minifluxClient.CategoryEntries(4, &miniflux.Filter{Statuses: []string{miniflux.EntryStatusUnread}})
|
|
if err != nil {
|
|
return MsgFetchedEntriesError(err)
|
|
}
|
|
|
|
var feedEntries []feedEntry
|
|
for _, e := range entriesResult.Entries {
|
|
feedEntries = append(feedEntries, feedEntry{
|
|
ID: e.ID,
|
|
Name: e.Title,
|
|
Feed: e.Feed.Title,
|
|
Link: e.URL,
|
|
PublishedAt: e.Date,
|
|
})
|
|
}
|
|
slices.Reverse(feedEntries)
|
|
|
|
return MsgFetchedEntries(feedEntries)
|
|
}
|
|
|
|
func (m *feedEntriesModel) Init() tea.Cmd {
|
|
m.entries = list.New([]list.Item{feedEntry{}}, list.NewDefaultDelegate(), 100, 50)
|
|
m.entries.Title = "Feed"
|
|
return m.fetchEntries
|
|
}
|
|
|
|
func (m *feedEntriesModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
switch msg := msg.(type) {
|
|
case tea.KeyMsg:
|
|
switch msg.String() {
|
|
case "enter":
|
|
fnGetSelected := func() tea.Msg {
|
|
i, ok := m.entries.SelectedItem().(feedEntry)
|
|
if ok {
|
|
m.selectedEntry = &i
|
|
}
|
|
|
|
return MsgPlayEntry(i)
|
|
}
|
|
|
|
return m, fnGetSelected
|
|
}
|
|
break
|
|
|
|
case MsgWatchedEntry:
|
|
m.markEntryRead(int64(msg))
|
|
|
|
case MsgFetchedEntries:
|
|
var items []list.Item
|
|
for _, e := range msg {
|
|
items = append(items, e)
|
|
}
|
|
m.entries.SetItems(items)
|
|
case MsgFetchedEntriesError:
|
|
break
|
|
}
|
|
|
|
var cmd tea.Cmd
|
|
m.entries, cmd = m.entries.Update(msg)
|
|
return m, cmd
|
|
}
|
|
|
|
func (m *feedEntriesModel) View() string {
|
|
return m.entries.View()
|
|
}
|
|
|
|
func (m *feedEntriesModel) markEntryRead(entryID int64) {
|
|
m.minifluxClient.UpdateEntries([]int64{entryID}, miniflux.EntryStatusRead)
|
|
}
|