From 5784bd7db3475a2bb236d03799672e50027ea634 Mon Sep 17 00:00:00 2001 From: isabel Date: Tue, 2 Jul 2024 15:03:31 +0100 Subject: [PATCH 01/21] refacotr: conext --- cmd/context.go | 19 +++++++ cmd/keys.go | 137 ++++++++++++++++++++++++++----------------------- cmd/load.go | 53 +++++++++++++------ cmd/main.go | 24 +++++---- cmd/modal.go | 14 ++--- cmd/render.go | 6 +-- cmd/view.go | 4 +- lib/config.go | 2 + lib/helpers.go | 7 +++ 9 files changed, 160 insertions(+), 106 deletions(-) create mode 100644 cmd/context.go diff --git a/cmd/context.go b/cmd/context.go new file mode 100644 index 0000000..51e50bb --- /dev/null +++ b/cmd/context.go @@ -0,0 +1,19 @@ +package cmd + +import ( + "github.com/isabelroses/izrss/lib" +) + +type context struct { + prev string + curr string + keys keyMap + feeds lib.Feeds + post lib.Post + feed lib.Feed +} + +func (m Model) swapPage(next string) { + m.context.prev = m.context.curr + m.context.curr = next +} diff --git a/cmd/keys.go b/cmd/keys.go index 23832b6..af17631 100644 --- a/cmd/keys.go +++ b/cmd/keys.go @@ -40,31 +40,7 @@ func (k keyMap) FullHelp() [][]key.Binding { } } -var keys = keyMap{ - Up: key.NewBinding( - key.WithKeys("up", "k"), - key.WithHelp("↑/k", "move up"), - ), - Down: key.NewBinding( - key.WithKeys("down", "j"), - key.WithHelp("↓/j", "move down"), - ), - Back: key.NewBinding( - key.WithKeys("left", "h", "shift+tab"), - key.WithHelp("←/h", "back"), - ), - Open: key.NewBinding( - key.WithKeys("enter", "o", "right", "l", "tab"), - key.WithHelp("o/enter", "open"), - ), - Help: key.NewBinding( - key.WithKeys("?"), - key.WithHelp("?", "toggle help"), - ), - Quit: key.NewBinding( - key.WithKeys("q", "esc", "ctrl+c"), - key.WithHelp("q/esc", "quit"), - ), +var allKeys = keyMap{ Refresh: key.NewBinding( key.WithKeys("r"), key.WithHelp("r", "refresh"), @@ -89,7 +65,7 @@ var keys = keyMap{ // TODO: refator this so its per page and not global func (m Model) handleKeys(msg tea.KeyMsg) (Model, tea.Cmd) { - if m.context == "search" { + if m.context.curr == "search" { switch msg.String() { case "enter": m = m.loadSearchValues() @@ -104,71 +80,71 @@ func (m Model) handleKeys(msg tea.KeyMsg) (Model, tea.Cmd) { } switch { - case key.Matches(msg, m.keys.Help): + case key.Matches(msg, m.context.keys.Help): m.help.ShowAll = !m.help.ShowAll - m.table.SetHeight(m.viewport.Height - lipgloss.Height(m.help.View(m.keys)) - lib.MainStyle.GetBorderBottomSize()) + m.table.SetHeight(m.viewport.Height - lipgloss.Height(m.help.View(m.context.keys)) - lib.MainStyle.GetBorderBottomSize()) - case key.Matches(msg, m.keys.Quit): - err := m.feeds.WriteTracking() + case key.Matches(msg, m.context.keys.Quit): + err := m.context.feeds.WriteTracking() if err != nil { log.Fatalf("Could not write tracking data: %s", err) } return m, tea.Quit - case key.Matches(msg, m.keys.Refresh): - switch m.context { + case key.Matches(msg, m.context.keys.Refresh): + switch m.context.curr { case "home": id := m.table.Cursor() - feed := &m.feeds[id] + feed := &m.context.feeds[id] lib.FetchURL(feed.URL, false) feed.Posts = lib.GetPosts(feed.URL) err := error(nil) - m.feeds, err = m.feeds.ReadTracking() + m.context.feeds, err = m.context.feeds.ReadTracking() if err != nil { log.Fatal(err) } m = m.loadHome() case "content": - feed := &m.feed + feed := &m.context.feed feed.Posts = lib.GetPosts(feed.URL) err := error(nil) - m.feeds, err = m.feeds.ReadTracking() + m.context.feeds, err = m.context.feeds.ReadTracking() if err != nil { log.Fatal(err) } - m = m.loadContent(m.feed.ID) + m = m.loadContent(m.context.feed.ID) default: return m, nil } - case key.Matches(msg, m.keys.RefreshAll): - if m.context == "home" { - m.feeds = lib.GetAllContent(lib.UserConfig.Urls, false) + case key.Matches(msg, m.context.keys.RefreshAll): + if m.context.curr == "home" { + m.context.feeds = lib.GetAllContent(lib.UserConfig.Urls, false) err := error(nil) - m.feeds, err = m.feeds.ReadTracking() + m.context.feeds, err = m.context.feeds.ReadTracking() if err != nil { log.Fatal(err) } m = m.loadHome() } - case key.Matches(msg, m.keys.Back): - switch m.context { + case key.Matches(msg, m.context.keys.Back): + switch m.context.curr { case "reader": - m = m.loadContent(m.feed.ID) - m.table.SetCursor(m.post.ID) + m = m.loadContent(m.context.feed.ID) + m.table.SetCursor(m.context.post.ID) case "content": m = m.loadHome() - m.table.SetCursor(m.feed.ID) + m.table.SetCursor(m.context.feed.ID) } m.viewport.SetYOffset(0) - case key.Matches(msg, m.keys.Open): - switch m.context { + case key.Matches(msg, m.context.keys.Open): + switch m.context.curr { case "reader": - err := lib.OpenURL(m.post.Link) + err := lib.OpenURL(m.context.post.Link) if err != nil { log.Panic(err) } @@ -182,39 +158,39 @@ func (m Model) handleKeys(msg tea.KeyMsg) (Model, tea.Cmd) { m.viewport.SetYOffset(0) } - case key.Matches(msg, m.keys.Search): - if m.context != "search" { + case key.Matches(msg, m.context.keys.Search): + if m.context.curr != "search" { m = m.loadSearch() } - case key.Matches(msg, m.keys.ToggleRead): - switch m.context { + case key.Matches(msg, m.context.keys.ToggleRead): + switch m.context.curr { case "reader": - lib.ToggleRead(m.feeds, m.feed.ID, m.post.ID) - m = m.loadContent(m.feed.ID) + lib.ToggleRead(m.context.feeds, m.context.feed.ID, m.context.post.ID) + m = m.loadContent(m.context.feed.ID) case "content": - lib.ToggleRead(m.feeds, m.feed.ID, m.table.Cursor()) - m = m.loadContent(m.feed.ID) + lib.ToggleRead(m.context.feeds, m.context.feed.ID, m.table.Cursor()) + m = m.loadContent(m.context.feed.ID) } - err := m.feeds.WriteTracking() + err := m.context.feeds.WriteTracking() if err != nil { log.Fatalf("Could not write tracking data: %s", err) } - case key.Matches(msg, m.keys.ReadAll): - switch m.context { + case key.Matches(msg, m.context.keys.ReadAll): + switch m.context.curr { case "reader": // if we are in the reader view, fall back to the normal mark all as read - lib.ToggleRead(m.feeds, m.feed.ID, m.post.ID) + lib.ToggleRead(m.context.feeds, m.context.feed.ID, m.context.post.ID) case "content": - lib.ReadAll(m.feeds, m.feed.ID) - m = m.loadContent(m.feed.ID) + lib.ReadAll(m.context.feeds, m.context.feed.ID) + m = m.loadContent(m.context.feed.ID) case "home": - lib.ReadAll(m.feeds, m.table.Cursor()) + lib.ReadAll(m.context.feeds, m.table.Cursor()) m = m.loadHome() } - err := m.feeds.WriteTracking() + err := m.context.feeds.WriteTracking() if err != nil { log.Fatalf("Could not write tracking data: %s", err) } @@ -222,3 +198,34 @@ func (m Model) handleKeys(msg tea.KeyMsg) (Model, tea.Cmd) { return m, nil } + +func defaultKeyMap(overrides ...keyMap) keyMap { + base := keyMap{ + Up: key.NewBinding( + key.WithKeys("up", "k"), + key.WithHelp("↑/k", "move up"), + ), + Down: key.NewBinding( + key.WithKeys("down", "j"), + key.WithHelp("↓/j", "move down"), + ), + Back: key.NewBinding( + key.WithKeys("left", "h", "shift+tab"), + key.WithHelp("←/h", "back"), + ), + Open: key.NewBinding( + key.WithKeys("enter", "o", "right", "l", "tab"), + key.WithHelp("o/enter", "open"), + ), + Help: key.NewBinding( + key.WithKeys("?"), + key.WithHelp("?", "toggle help"), + ), + Quit: key.NewBinding( + key.WithKeys("q", "esc", "ctrl+c"), + key.WithHelp("q/esc", "quit"), + ), + } + + return keys +} diff --git a/cmd/load.go b/cmd/load.go index 75a72ff..602468a 100644 --- a/cmd/load.go +++ b/cmd/load.go @@ -18,46 +18,69 @@ func (m Model) loadHome() Model { } rows := []table.Row{} - for _, Feed := range m.feeds { + for _, Feed := range m.context.feeds { totalUnread := strconv.Itoa(Feed.GetTotalUnreads()) fraction := fmt.Sprintf("%s/%d", totalUnread, len(Feed.Posts)) rows = append(rows, table.Row{fraction, Feed.Title}) } - m.context = "home" + m.context.curr = "home" m = m.loadNewTable(columns, rows) return m } +func (m Model) loadMixed() Model { + columns := []table.Column{ + {Title: "Date", Width: 15}, + {Title: "Read", Width: 10}, + {Title: "Title", Width: m.table.Width() - 25}, + } + + posts := []lib.Post{} + for _, feed := range m.context.feeds { + posts = append(posts, feed.Posts...) + } + + rows := []table.Row{} + for _, post := range posts { + read := lib.ReadSymbol(post.Read) + rows = append(rows, table.Row{post.Date, read, post.Title}) + } + + m.context.feed.Posts = posts + + m = m.loadNewTable(columns, rows) + m.swapPage("mixed") + + return m +} + func (m Model) loadContent(id int) Model { - feed := m.feeds[id] + feed := m.context.feeds[id] feed.ID = id columns := []table.Column{ + {Title: "", Width: 10}, {Title: "Date", Width: 15}, - {Title: "Read", Width: 10}, {Title: "Title", Width: m.table.Width() - 25}, } rows := []table.Row{} for _, post := range feed.Posts { - read := "x" - if post.Read { - read = "✓" - } - rows = append(rows, table.Row{post.Date, read, post.Title}) + readsym := lib.ReadSymbol(post.Read) + rows = append(rows, table.Row{readsym, post.Date, post.Title}) } m = m.loadNewTable(columns, rows) - m.context = "content" - m.feed = feed + m.swapPage("content") + m.context.feed = feed return m } func (m Model) loadSearch() Model { - m.context = "search" + m.swapPage("search") m.table.Blur() @@ -73,7 +96,7 @@ func (m Model) loadSearchValues() Model { var filteredPosts []lib.Post rows := []table.Row{} - for _, feed := range m.feeds { + for _, feed := range m.context.feeds { for _, post := range feed.Posts { if strings.Contains(strings.ToLower(post.Content), strings.ToLower(search)) { filteredPosts = append(filteredPosts, post) @@ -88,8 +111,8 @@ func (m Model) loadSearchValues() Model { } m = m.loadNewTable(columns, rows) - m.context = "content" - m.feed.Posts = filteredPosts + m.swapPage("content") + m.context.feed.Posts = filteredPosts m.table.Focus() m.filter.Blur() m.table.SetCursor(0) diff --git a/cmd/main.go b/cmd/main.go index 1308d79..0a1ac1e 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -39,14 +39,14 @@ func (m Model) handleWindowSize(msg tea.WindowSizeMsg) Model { width := msg.Width - framew m.table.SetWidth(width) - m.table.SetHeight(height - lipgloss.Height(m.help.View(m.keys)) - lib.MainStyle.GetBorderBottomSize()) + m.table.SetHeight(height - lipgloss.Height(m.help.View(m.context.keys)) - lib.MainStyle.GetBorderBottomSize()) if !m.ready { - m.feeds = lib.GetAllContent(lib.UserConfig.Urls, lib.CheckCache()) + m.context.feeds = lib.GetAllContent(lib.UserConfig.Urls, lib.CheckCache()) m.viewport = viewport.New(width, height) err := error(nil) - m.feeds, err = m.feeds.ReadTracking() + m.context.feeds, err = m.context.feeds.ReadTracking() if err != nil { log.Fatalf("could not read tracking file: %v", err) } @@ -74,7 +74,11 @@ func (m Model) handleWindowSize(msg tea.WindowSizeMsg) Model { glamWidth, ) - m = m.loadHome() + if lib.UserConfig.Home == "mixed" { + m = m.loadMixed() + } else { + m = m.loadHome() + } m.ready = true } else { @@ -96,14 +100,14 @@ func (m Model) updateViewport(msg tea.Msg) (Model, tea.Cmd) { m.table, cmd = m.table.Update(msg) cmds = append(cmds, cmd) - if m.context != "reader" && m.context != "search" { + if m.context.curr != "reader" && m.context.curr != "search" { view := lipgloss.JoinVertical( lipgloss.Top, m.table.View(), - m.help.View(m.keys), + m.help.View(m.context.keys), ) m.viewport.SetContent(view) - } else if m.context == "search" { + } else if m.context.curr == "search" { m.filter, cmd = m.filter.Update(msg) cmds = append(cmds, cmd) @@ -111,14 +115,14 @@ func (m Model) updateViewport(msg tea.Msg) (Model, tea.Cmd) { lipgloss.Top, m.filter.View(), m.table.View(), - m.help.View(m.keys), + m.help.View(m.context.keys), ) m.viewport.SetContent(view) } - if m.context == "reader" && m.viewport.ScrollPercent() >= lib.UserConfig.Reader.ReadThreshold { - lib.MarkRead(m.feeds, m.feed.ID, m.post.ID) + if m.context.curr == "reader" && m.viewport.ScrollPercent() >= lib.UserConfig.Reader.ReadThreshold { + lib.MarkRead(m.context.feeds, m.context.feed.ID, m.context.post.ID) } m.viewport, cmd = m.viewport.Update(msg) diff --git a/cmd/modal.go b/cmd/modal.go index 4146f19..2c78448 100644 --- a/cmd/modal.go +++ b/cmd/modal.go @@ -15,16 +15,12 @@ import ( // Model is the main model for the application type Model struct { help help.Model - context string - keys keyMap + glam *glamour.TermRenderer + context context viewport viewport.Model - feeds lib.Feeds filter textinput.Model - post lib.Post - feed lib.Feed table table.Model ready bool - glam *glamour.TermRenderer } // Init sets the initial state of the model @@ -56,15 +52,11 @@ func NewModel() Model { h.Styles.ShortSeparator = lib.HelpStyle return Model{ - context: "", - feeds: lib.Feeds{}, - feed: lib.Feed{}, + context: context{}, viewport: viewport.Model{}, table: t, ready: false, - keys: keys, help: h, - post: lib.Post{}, filter: f, } } diff --git a/cmd/render.go b/cmd/render.go index 07c350e..9790b4e 100644 --- a/cmd/render.go +++ b/cmd/render.go @@ -10,11 +10,11 @@ var htom = tomd.NewConverter("", true, nil) func (m Model) loadReader() Model { id := m.table.Cursor() - post := m.feed.Posts[id] + post := m.context.feed.Posts[id] post.ID = id - m.context = "reader" - m.post = post + m.swapPage("reader") + m.context.post = post m.viewport.YPosition = 0 // reset the viewport position // render the post diff --git a/cmd/view.go b/cmd/view.go index 17c2619..cfd01e9 100644 --- a/cmd/view.go +++ b/cmd/view.go @@ -9,7 +9,7 @@ import ( ) func (m Model) headerView() string { - title := lib.ReaderStyle.Render(m.post.Title) + title := lib.ReaderStyle.Render(m.context.post.Title) line := strings.Repeat("─", lib.Max(0, m.viewport.Width-lipgloss.Width(title))) return lipgloss.JoinHorizontal(lipgloss.Center, title, line) } @@ -26,7 +26,7 @@ func (m Model) View() string { if !m.ready { out = "Initializing..." - } else if m.context == "reader" { + } else if m.context.curr == "reader" { out = lipgloss.JoinVertical( lipgloss.Top, m.headerView(), diff --git a/lib/config.go b/lib/config.go index 3eb1ea9..8ae44ab 100644 --- a/lib/config.go +++ b/lib/config.go @@ -32,6 +32,7 @@ func LoadConfig(config string) { // UserConfig is the global user configuration var UserConfig = config{ + Home: "home", DateFormat: "02/01/2006", Urls: []string{}, Reader: reader{ @@ -49,6 +50,7 @@ var UserConfig = config{ // Config is the struct that holds the configuration type config struct { + Home string `toml:"home"` Colors colors `toml:"colors"` Reader reader `toml:"reader"` DateFormat string `toml:"dateformat"` diff --git a/lib/helpers.go b/lib/helpers.go index 4739ad7..a006bdf 100644 --- a/lib/helpers.go +++ b/lib/helpers.go @@ -103,3 +103,10 @@ func Max(a, b int) int { } return b } + +func ReadSymbol(read bool) string { + if read { + return " " + } + return "•" +} From 96f6be579f8368b1ac9e521cc7e611c296a6849b Mon Sep 17 00:00:00 2001 From: isabel Date: Wed, 3 Jul 2024 11:50:12 +0100 Subject: [PATCH 02/21] refactor: continues --- cmd/context.go | 3 +- cmd/help.go | 224 ++++++++++++++++++++++++++++++++++++ cmd/keys.go | 300 ++++++++++++++++++++++++++----------------------- cmd/load.go | 4 +- cmd/main.go | 6 +- cmd/modal.go | 7 +- 6 files changed, 396 insertions(+), 148 deletions(-) create mode 100644 cmd/help.go diff --git a/cmd/context.go b/cmd/context.go index 51e50bb..9888220 100644 --- a/cmd/context.go +++ b/cmd/context.go @@ -7,13 +7,12 @@ import ( type context struct { prev string curr string - keys keyMap feeds lib.Feeds post lib.Post feed lib.Feed } -func (m Model) swapPage(next string) { +func (m *Model) swapPage(next string) { m.context.prev = m.context.curr m.context.curr = next } diff --git a/cmd/help.go b/cmd/help.go new file mode 100644 index 0000000..52a792f --- /dev/null +++ b/cmd/help.go @@ -0,0 +1,224 @@ +package cmd + +// modified from https://github.com/charmbracelet/bubbles/blob/master/help/help.go +// I did this so it would be easier to pass context to the help model + +import ( + "strings" + + "github.com/charmbracelet/bubbles/key" + tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/lipgloss" +) + +// KeyMap is a map of keybindings used to generate help. Since it's an +// interface it can be any type, though struct or a map[string][]key.Binding +// are likely candidates. +// +// Note that if a key is disabled (via key.Binding.SetEnabled) it will not be +// rendered in the help view, so in theory generated help should self-manage. +type KeyMap interface { + // ShortHelp returns a slice of bindings to be displayed in the short + // version of the help. The help bubble will render help in the order in + // which the help items are returned here. + ShortHelp() []key.Binding + + // FullHelp returns an extended group of help items, grouped by columns. + // The help bubble will render the help in the order in which the help + // items are returned here. + FullHelp(m Model) [][]key.Binding +} + +// Styles is a set of available style definitions for the Help bubble. +type Styles struct { + Ellipsis lipgloss.Style + + // Styling for the short help + ShortKey lipgloss.Style + ShortDesc lipgloss.Style + ShortSeparator lipgloss.Style + + // Styling for the full help + FullKey lipgloss.Style + FullDesc lipgloss.Style + FullSeparator lipgloss.Style +} + +// KeyModel contains the state of the help view. +type KeyModel struct { + Styles Styles + ShortSeparator string + FullSeparator string + Ellipsis string + Width int + ShowAll bool +} + +// New creates a new help view with some useful defaults. +func NewHelp() KeyModel { + keyStyle := lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{ + Light: "#909090", + Dark: "#626262", + }) + + descStyle := lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{ + Light: "#B2B2B2", + Dark: "#4A4A4A", + }) + + sepStyle := lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{ + Light: "#DDDADA", + Dark: "#3C3C3C", + }) + + return KeyModel{ + ShortSeparator: " • ", + FullSeparator: " ", + Ellipsis: "…", + Styles: Styles{ + ShortKey: keyStyle, + ShortDesc: descStyle, + ShortSeparator: sepStyle, + Ellipsis: sepStyle, + FullKey: keyStyle, + FullDesc: descStyle, + FullSeparator: sepStyle, + }, + } +} + +// Update helps satisfy the Bubble Tea Model interface. It's a no-op. +func (m KeyModel) Update(_ tea.Msg) (KeyModel, tea.Cmd) { + return m, nil +} + +// View renders the help view's current state. +func (km KeyModel) View(k KeyMap, m Model) string { + if km.ShowAll { + return km.FullHelpView(k.FullHelp(m)) + } + return km.ShortHelpView(k.ShortHelp()) +} + +// ShortHelpView renders a single line help view from a slice of keybindings. +// If the line is longer than the maximum width it will be gracefully +// truncated, showing only as many help items as possible. +func (m KeyModel) ShortHelpView(bindings []key.Binding) string { + if len(bindings) == 0 { + return "" + } + + var b strings.Builder + var totalWidth int + separator := m.Styles.ShortSeparator.Inline(true).Render(m.ShortSeparator) + + for i, kb := range bindings { + if !kb.Enabled() { + continue + } + + var sep string + if totalWidth > 0 && i < len(bindings) { + sep = separator + } + + str := sep + + m.Styles.ShortKey.Inline(true).Render(kb.Help().Key) + " " + + m.Styles.ShortDesc.Inline(true).Render(kb.Help().Desc) + + w := lipgloss.Width(str) + + // If adding this help item would go over the available width, stop + // drawing. + if m.Width > 0 && totalWidth+w > m.Width { + // Although if there's room for an ellipsis, print that. + tail := " " + m.Styles.Ellipsis.Inline(true).Render(m.Ellipsis) + tailWidth := lipgloss.Width(tail) + + if totalWidth+tailWidth < m.Width { + b.WriteString(tail) + } + + break + } + + totalWidth += w + b.WriteString(str) + } + + return b.String() +} + +// FullHelpView renders help columns from a slice of key binding slices. Each +// top level slice entry renders into a column. +func (m KeyModel) FullHelpView(groups [][]key.Binding) string { + if len(groups) == 0 { + return "" + } + + // Linter note: at this time we don't think it's worth the additional + // code complexity involved in preallocating this slice. + //nolint:prealloc + var ( + out []string + + totalWidth int + sep = m.Styles.FullSeparator.Render(m.FullSeparator) + sepWidth = lipgloss.Width(sep) + ) + + // Iterate over groups to build columns + for i, group := range groups { + if group == nil || !shouldRenderColumn(group) { + continue + } + + var ( + keys []string + descriptions []string + ) + + // Separate keys and descriptions into different slices + for _, kb := range group { + if !kb.Enabled() { + continue + } + keys = append(keys, kb.Help().Key) + descriptions = append(descriptions, kb.Help().Desc) + } + + col := lipgloss.JoinHorizontal(lipgloss.Top, + m.Styles.FullKey.Render(strings.Join(keys, "\n")), + m.Styles.FullKey.Render(" "), + m.Styles.FullDesc.Render(strings.Join(descriptions, "\n")), + ) + + // Column + totalWidth += lipgloss.Width(col) + if m.Width > 0 && totalWidth > m.Width { + break + } + + out = append(out, col) + + // Separator + if i < len(group)-1 { + totalWidth += sepWidth + if m.Width > 0 && totalWidth > m.Width { + break + } + out = append(out, sep) + } + } + + return lipgloss.JoinHorizontal(lipgloss.Top, out...) +} + +func shouldRenderColumn(b []key.Binding) (ok bool) { + for _, v := range b { + if v.Enabled() { + return true + } + } + return false +} diff --git a/cmd/keys.go b/cmd/keys.go index af17631..d83de28 100644 --- a/cmd/keys.go +++ b/cmd/keys.go @@ -29,71 +29,52 @@ func (k keyMap) ShortHelp() []key.Binding { return []key.Binding{k.Help, k.Quit} } -func (k keyMap) FullHelp() [][]key.Binding { - return [][]key.Binding{ - {k.Up, k.Down}, - {k.Back, k.Open}, - {k.Search}, - {k.Refresh, k.RefreshAll}, - {k.ToggleRead, k.ReadAll}, - {k.Help, k.Quit}, +func (k keyMap) FullHelp(m Model) [][]key.Binding { + var help [][]key.Binding + + switch m.context.curr { + case "home": + help = [][]key.Binding{ + {k.Up, k.Down}, + {k.Back, k.Open}, + {k.Search}, + {k.Refresh, k.RefreshAll}, + {k.ReadAll}, + {k.Help, k.Quit}, + } + case "content": + help = [][]key.Binding{ + {k.Up, k.Down}, + {k.Back, k.Open}, + {k.Search}, + {k.Refresh, k.RefreshAll}, + {k.ToggleRead, k.ReadAll}, + {k.Help, k.Quit}, + } + case "reader": + help = [][]key.Binding{ + {k.Up, k.Down}, + {k.Back, k.Open}, + {k.ToggleRead}, + {k.Help, k.Quit}, + } } -} -var allKeys = keyMap{ - Refresh: key.NewBinding( - key.WithKeys("r"), - key.WithHelp("r", "refresh"), - ), - RefreshAll: key.NewBinding( - key.WithKeys("R"), - key.WithHelp("R", "refresh all"), - ), - Search: key.NewBinding( - key.WithKeys("/"), - key.WithHelp("/", "search"), - ), - ToggleRead: key.NewBinding( - key.WithKeys("x"), - key.WithHelp("x", "toggle read"), - ), - ReadAll: key.NewBinding( - key.WithKeys("X"), - key.WithHelp("X", "mark all as read"), - ), + return help } // TODO: refator this so its per page and not global func (m Model) handleKeys(msg tea.KeyMsg) (Model, tea.Cmd) { - if m.context.curr == "search" { - switch msg.String() { - case "enter": - m = m.loadSearchValues() - - case "ctrl+c", "esc", "/": + // handle page specific keys + switch m.context.curr { + case "home": + switch { + case key.Matches(msg, m.keys.Open): m = m.loadContent(m.table.Cursor()) - m.table.Focus() - m.filter.Blur() - } - - return m, nil - } - - switch { - case key.Matches(msg, m.context.keys.Help): - m.help.ShowAll = !m.help.ShowAll - m.table.SetHeight(m.viewport.Height - lipgloss.Height(m.help.View(m.context.keys)) - lib.MainStyle.GetBorderBottomSize()) - - case key.Matches(msg, m.context.keys.Quit): - err := m.context.feeds.WriteTracking() - if err != nil { - log.Fatalf("Could not write tracking data: %s", err) - } - return m, tea.Quit + m.table.SetCursor(0) + m.viewport.SetYOffset(0) - case key.Matches(msg, m.context.keys.Refresh): - switch m.context.curr { - case "home": + case key.Matches(msg, m.keys.Refresh): id := m.table.Cursor() feed := &m.context.feeds[id] lib.FetchURL(feed.URL, false) @@ -105,127 +86,170 @@ func (m Model) handleKeys(msg tea.KeyMsg) (Model, tea.Cmd) { } m = m.loadHome() - case "content": - feed := &m.context.feed - feed.Posts = lib.GetPosts(feed.URL) + case key.Matches(msg, m.keys.RefreshAll): + m.context.feeds = lib.GetAllContent(lib.UserConfig.Urls, false) err := error(nil) m.context.feeds, err = m.context.feeds.ReadTracking() if err != nil { log.Fatal(err) } - m = m.loadContent(m.context.feed.ID) + m = m.loadHome() - default: - return m, nil + case key.Matches(msg, m.keys.ReadAll): + lib.ReadAll(m.context.feeds, m.table.Cursor()) + m = m.loadHome() + err := m.context.feeds.WriteTracking() + if err != nil { + log.Fatalf("Could not write tracking data: %s", err) + } } - case key.Matches(msg, m.context.keys.RefreshAll): - if m.context.curr == "home" { - m.context.feeds = lib.GetAllContent(lib.UserConfig.Urls, false) + case "content": + switch { + case key.Matches(msg, m.keys.Refresh): + feed := &m.context.feed + feed.Posts = lib.GetPosts(feed.URL) err := error(nil) m.context.feeds, err = m.context.feeds.ReadTracking() if err != nil { log.Fatal(err) } + m = m.loadContent(m.context.feed.ID) + + case key.Matches(msg, m.keys.Back): m = m.loadHome() + m.table.SetCursor(m.context.feed.ID) + m.viewport.SetYOffset(0) + + case key.Matches(msg, m.keys.Open): + m = m.loadReader() + + case key.Matches(msg, m.keys.ToggleRead): + lib.ToggleRead(m.context.feeds, m.context.feed.ID, m.table.Cursor()) + m = m.loadContent(m.context.feed.ID) + err := m.context.feeds.WriteTracking() + if err != nil { + log.Fatalf("Could not write tracking data: %s", err) + } + + case key.Matches(msg, m.keys.ReadAll): + lib.ReadAll(m.context.feeds, m.context.feed.ID) + m = m.loadContent(m.context.feed.ID) + err := m.context.feeds.WriteTracking() + if err != nil { + log.Fatalf("Could not write tracking data: %s", err) + } } - case key.Matches(msg, m.context.keys.Back): - switch m.context.curr { - case "reader": + case "reader": + switch { + case key.Matches(msg, m.keys.Back): m = m.loadContent(m.context.feed.ID) m.table.SetCursor(m.context.post.ID) - case "content": - m = m.loadHome() - m.table.SetCursor(m.context.feed.ID) - } - m.viewport.SetYOffset(0) + m.viewport.SetYOffset(0) - case key.Matches(msg, m.context.keys.Open): - switch m.context.curr { - case "reader": + case key.Matches(msg, m.keys.Open): err := lib.OpenURL(m.context.post.Link) if err != nil { log.Panic(err) } - case "content": - m = m.loadReader() + case key.Matches(msg, m.keys.ToggleRead): + lib.ToggleRead(m.context.feeds, m.context.feed.ID, m.context.post.ID) + m = m.loadContent(m.context.feed.ID) + err := m.context.feeds.WriteTracking() + if err != nil { + log.Fatalf("Could not write tracking data: %s", err) + } - default: + case key.Matches(msg, m.keys.ReadAll): + // if we are in the reader view, fall back to the normal mark all as read + lib.ToggleRead(m.context.feeds, m.context.feed.ID, m.context.post.ID) + err := m.context.feeds.WriteTracking() + if err != nil { + log.Fatalf("Could not write tracking data: %s", err) + } + } + + case "search": + switch msg.String() { + case "enter": + m = m.loadSearchValues() + + case "ctrl+c", "esc", "/": m = m.loadContent(m.table.Cursor()) - m.table.SetCursor(0) - m.viewport.SetYOffset(0) + m.table.Focus() + m.filter.Blur() + + return m, nil } + } - case key.Matches(msg, m.context.keys.Search): + // handle global keys + switch { + case key.Matches(msg, m.keys.Search): if m.context.curr != "search" { m = m.loadSearch() } - case key.Matches(msg, m.context.keys.ToggleRead): - switch m.context.curr { - case "reader": - lib.ToggleRead(m.context.feeds, m.context.feed.ID, m.context.post.ID) - m = m.loadContent(m.context.feed.ID) - case "content": - lib.ToggleRead(m.context.feeds, m.context.feed.ID, m.table.Cursor()) - m = m.loadContent(m.context.feed.ID) - } - err := m.context.feeds.WriteTracking() - if err != nil { - log.Fatalf("Could not write tracking data: %s", err) - } - - case key.Matches(msg, m.context.keys.ReadAll): - switch m.context.curr { - case "reader": - // if we are in the reader view, fall back to the normal mark all as read - lib.ToggleRead(m.context.feeds, m.context.feed.ID, m.context.post.ID) - case "content": - lib.ReadAll(m.context.feeds, m.context.feed.ID) - m = m.loadContent(m.context.feed.ID) - case "home": - lib.ReadAll(m.context.feeds, m.table.Cursor()) - m = m.loadHome() - } + case key.Matches(msg, m.keys.Help): + m.help.ShowAll = !m.help.ShowAll + m.table.SetHeight(m.viewport.Height - lipgloss.Height(m.help.View(m.keys, m)) - lib.MainStyle.GetBorderBottomSize()) + case key.Matches(msg, m.keys.Quit): err := m.context.feeds.WriteTracking() if err != nil { log.Fatalf("Could not write tracking data: %s", err) } + return m, tea.Quit } return m, nil } -func defaultKeyMap(overrides ...keyMap) keyMap { - base := keyMap{ - Up: key.NewBinding( - key.WithKeys("up", "k"), - key.WithHelp("↑/k", "move up"), - ), - Down: key.NewBinding( - key.WithKeys("down", "j"), - key.WithHelp("↓/j", "move down"), - ), - Back: key.NewBinding( - key.WithKeys("left", "h", "shift+tab"), - key.WithHelp("←/h", "back"), - ), - Open: key.NewBinding( - key.WithKeys("enter", "o", "right", "l", "tab"), - key.WithHelp("o/enter", "open"), - ), - Help: key.NewBinding( - key.WithKeys("?"), - key.WithHelp("?", "toggle help"), - ), - Quit: key.NewBinding( - key.WithKeys("q", "esc", "ctrl+c"), - key.WithHelp("q/esc", "quit"), - ), - } - - return keys +var keys = keyMap{ + Up: key.NewBinding( + key.WithKeys("up", "k"), + key.WithHelp("↑/k", "move up"), + ), + Down: key.NewBinding( + key.WithKeys("down", "j"), + key.WithHelp("↓/j", "move down"), + ), + Back: key.NewBinding( + key.WithKeys("left", "h", "shift+tab"), + key.WithHelp("←/h", "back"), + ), + Open: key.NewBinding( + key.WithKeys("enter", "o", "right", "l", "tab"), + key.WithHelp("o/enter", "open"), + ), + Help: key.NewBinding( + key.WithKeys("?"), + key.WithHelp("?", "toggle help"), + ), + Quit: key.NewBinding( + key.WithKeys("q", "esc", "ctrl+c"), + key.WithHelp("q/esc", "quit"), + ), + Refresh: key.NewBinding( + key.WithKeys("r"), + key.WithHelp("r", "refresh"), + ), + RefreshAll: key.NewBinding( + key.WithKeys("R"), + key.WithHelp("R", "refresh all"), + ), + Search: key.NewBinding( + key.WithKeys("/"), + key.WithHelp("/", "search"), + ), + ToggleRead: key.NewBinding( + key.WithKeys("x"), + key.WithHelp("x", "toggle read"), + ), + ReadAll: key.NewBinding( + key.WithKeys("X"), + key.WithHelp("X", "mark all as read"), + ), } diff --git a/cmd/load.go b/cmd/load.go index 602468a..07034dd 100644 --- a/cmd/load.go +++ b/cmd/load.go @@ -24,7 +24,7 @@ func (m Model) loadHome() Model { rows = append(rows, table.Row{fraction, Feed.Title}) } - m.context.curr = "home" + m.swapPage("home") m = m.loadNewTable(columns, rows) return m @@ -61,7 +61,7 @@ func (m Model) loadContent(id int) Model { feed.ID = id columns := []table.Column{ - {Title: "", Width: 10}, + {Title: "", Width: 2}, {Title: "Date", Width: 15}, {Title: "Title", Width: m.table.Width() - 25}, } diff --git a/cmd/main.go b/cmd/main.go index 0a1ac1e..a832b77 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -39,7 +39,7 @@ func (m Model) handleWindowSize(msg tea.WindowSizeMsg) Model { width := msg.Width - framew m.table.SetWidth(width) - m.table.SetHeight(height - lipgloss.Height(m.help.View(m.context.keys)) - lib.MainStyle.GetBorderBottomSize()) + m.table.SetHeight(height - lipgloss.Height(m.help.View(m.keys, m)) - lib.MainStyle.GetBorderBottomSize()) if !m.ready { m.context.feeds = lib.GetAllContent(lib.UserConfig.Urls, lib.CheckCache()) @@ -104,7 +104,7 @@ func (m Model) updateViewport(msg tea.Msg) (Model, tea.Cmd) { view := lipgloss.JoinVertical( lipgloss.Top, m.table.View(), - m.help.View(m.context.keys), + m.help.View(m.keys, m), ) m.viewport.SetContent(view) } else if m.context.curr == "search" { @@ -115,7 +115,7 @@ func (m Model) updateViewport(msg tea.Msg) (Model, tea.Cmd) { lipgloss.Top, m.filter.View(), m.table.View(), - m.help.View(m.context.keys), + m.help.View(m.keys, m), ) m.viewport.SetContent(view) diff --git a/cmd/modal.go b/cmd/modal.go index 2c78448..67b8f0b 100644 --- a/cmd/modal.go +++ b/cmd/modal.go @@ -1,7 +1,6 @@ package cmd import ( - "github.com/charmbracelet/bubbles/help" "github.com/charmbracelet/bubbles/table" "github.com/charmbracelet/bubbles/textinput" "github.com/charmbracelet/bubbles/viewport" @@ -14,7 +13,8 @@ import ( // Model is the main model for the application type Model struct { - help help.Model + help KeyModel + keys keyMap glam *glamour.TermRenderer context context viewport viewport.Model @@ -43,7 +43,7 @@ func NewModel() Model { Bold(true). Foreground(lipgloss.Color("229")) - h := help.New() + h := NewHelp() h.Styles.FullKey = lib.HelpStyle h.Styles.FullDesc = lib.HelpStyle h.Styles.FullSeparator = lib.HelpStyle @@ -57,6 +57,7 @@ func NewModel() Model { table: t, ready: false, help: h, + keys: keys, filter: f, } } From 3a0b7e04f61ecf9a218fb2d38c4ecbf0d4b6f90e Mon Sep 17 00:00:00 2001 From: isabel Date: Wed, 3 Jul 2024 12:29:26 +0100 Subject: [PATCH 03/21] refactor: use pointers where possible --- cmd/keys.go | 28 ++++++++++++++-------------- cmd/load.go | 32 ++++++++++---------------------- cmd/main.go | 4 ++-- cmd/render.go | 4 +--- 4 files changed, 27 insertions(+), 41 deletions(-) diff --git a/cmd/keys.go b/cmd/keys.go index d83de28..4d2bc46 100644 --- a/cmd/keys.go +++ b/cmd/keys.go @@ -70,7 +70,7 @@ func (m Model) handleKeys(msg tea.KeyMsg) (Model, tea.Cmd) { case "home": switch { case key.Matches(msg, m.keys.Open): - m = m.loadContent(m.table.Cursor()) + m.loadContent(m.table.Cursor()) m.table.SetCursor(0) m.viewport.SetYOffset(0) @@ -84,7 +84,7 @@ func (m Model) handleKeys(msg tea.KeyMsg) (Model, tea.Cmd) { if err != nil { log.Fatal(err) } - m = m.loadHome() + m.loadHome() case key.Matches(msg, m.keys.RefreshAll): m.context.feeds = lib.GetAllContent(lib.UserConfig.Urls, false) @@ -93,11 +93,11 @@ func (m Model) handleKeys(msg tea.KeyMsg) (Model, tea.Cmd) { if err != nil { log.Fatal(err) } - m = m.loadHome() + m.loadHome() case key.Matches(msg, m.keys.ReadAll): lib.ReadAll(m.context.feeds, m.table.Cursor()) - m = m.loadHome() + m.loadHome() err := m.context.feeds.WriteTracking() if err != nil { log.Fatalf("Could not write tracking data: %s", err) @@ -114,19 +114,19 @@ func (m Model) handleKeys(msg tea.KeyMsg) (Model, tea.Cmd) { if err != nil { log.Fatal(err) } - m = m.loadContent(m.context.feed.ID) + m.loadContent(m.context.feed.ID) case key.Matches(msg, m.keys.Back): - m = m.loadHome() + m.loadHome() m.table.SetCursor(m.context.feed.ID) m.viewport.SetYOffset(0) case key.Matches(msg, m.keys.Open): - m = m.loadReader() + m.loadReader() case key.Matches(msg, m.keys.ToggleRead): lib.ToggleRead(m.context.feeds, m.context.feed.ID, m.table.Cursor()) - m = m.loadContent(m.context.feed.ID) + m.loadContent(m.context.feed.ID) err := m.context.feeds.WriteTracking() if err != nil { log.Fatalf("Could not write tracking data: %s", err) @@ -134,7 +134,7 @@ func (m Model) handleKeys(msg tea.KeyMsg) (Model, tea.Cmd) { case key.Matches(msg, m.keys.ReadAll): lib.ReadAll(m.context.feeds, m.context.feed.ID) - m = m.loadContent(m.context.feed.ID) + m.loadContent(m.context.feed.ID) err := m.context.feeds.WriteTracking() if err != nil { log.Fatalf("Could not write tracking data: %s", err) @@ -144,7 +144,7 @@ func (m Model) handleKeys(msg tea.KeyMsg) (Model, tea.Cmd) { case "reader": switch { case key.Matches(msg, m.keys.Back): - m = m.loadContent(m.context.feed.ID) + m.loadContent(m.context.feed.ID) m.table.SetCursor(m.context.post.ID) m.viewport.SetYOffset(0) @@ -156,7 +156,7 @@ func (m Model) handleKeys(msg tea.KeyMsg) (Model, tea.Cmd) { case key.Matches(msg, m.keys.ToggleRead): lib.ToggleRead(m.context.feeds, m.context.feed.ID, m.context.post.ID) - m = m.loadContent(m.context.feed.ID) + m.loadContent(m.context.feed.ID) err := m.context.feeds.WriteTracking() if err != nil { log.Fatalf("Could not write tracking data: %s", err) @@ -174,10 +174,10 @@ func (m Model) handleKeys(msg tea.KeyMsg) (Model, tea.Cmd) { case "search": switch msg.String() { case "enter": - m = m.loadSearchValues() + m.loadSearchValues() case "ctrl+c", "esc", "/": - m = m.loadContent(m.table.Cursor()) + m.loadContent(m.table.Cursor()) m.table.Focus() m.filter.Blur() @@ -189,7 +189,7 @@ func (m Model) handleKeys(msg tea.KeyMsg) (Model, tea.Cmd) { switch { case key.Matches(msg, m.keys.Search): if m.context.curr != "search" { - m = m.loadSearch() + m.loadSearch() } case key.Matches(msg, m.keys.Help): diff --git a/cmd/load.go b/cmd/load.go index 07034dd..1aba72f 100644 --- a/cmd/load.go +++ b/cmd/load.go @@ -11,7 +11,7 @@ import ( ) // load the home view, this conists of the list of feeds -func (m Model) loadHome() Model { +func (m *Model) loadHome() { columns := []table.Column{ {Title: "Unread", Width: 10}, {Title: "Title", Width: m.table.Width() - 10}, @@ -25,12 +25,10 @@ func (m Model) loadHome() Model { } m.swapPage("home") - m = m.loadNewTable(columns, rows) - - return m + m.loadNewTable(columns, rows) } -func (m Model) loadMixed() Model { +func (m *Model) loadMixed() { columns := []table.Column{ {Title: "Date", Width: 15}, {Title: "Read", Width: 10}, @@ -50,13 +48,11 @@ func (m Model) loadMixed() Model { m.context.feed.Posts = posts - m = m.loadNewTable(columns, rows) + m.loadNewTable(columns, rows) m.swapPage("mixed") - - return m } -func (m Model) loadContent(id int) Model { +func (m *Model) loadContent(id int) { feed := m.context.feeds[id] feed.ID = id @@ -72,25 +68,21 @@ func (m Model) loadContent(id int) Model { rows = append(rows, table.Row{readsym, post.Date, post.Title}) } - m = m.loadNewTable(columns, rows) + m.loadNewTable(columns, rows) m.swapPage("content") m.context.feed = feed - - return m } -func (m Model) loadSearch() Model { +func (m *Model) loadSearch() { m.swapPage("search") m.table.Blur() m.filter.Focus() m.filter.SetValue("") - - return m } -func (m Model) loadSearchValues() Model { +func (m Model) loadSearchValues() { search := m.filter.Value() var filteredPosts []lib.Post @@ -110,17 +102,15 @@ func (m Model) loadSearchValues() Model { {Title: "Title", Width: m.table.Width() - 15}, } - m = m.loadNewTable(columns, rows) + m.loadNewTable(columns, rows) m.swapPage("content") m.context.feed.Posts = filteredPosts m.table.Focus() m.filter.Blur() m.table.SetCursor(0) - - return m } -func (m Model) loadNewTable(columns []table.Column, rows []table.Row) Model { +func (m *Model) loadNewTable(columns []table.Column, rows []table.Row) { t := &m.table // NOTE: clear the rows first to prevent panic @@ -128,6 +118,4 @@ func (m Model) loadNewTable(columns []table.Column, rows []table.Row) Model { t.SetColumns(columns) t.SetRows(rows) - - return m } diff --git a/cmd/main.go b/cmd/main.go index a832b77..c32de44 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -75,9 +75,9 @@ func (m Model) handleWindowSize(msg tea.WindowSizeMsg) Model { ) if lib.UserConfig.Home == "mixed" { - m = m.loadMixed() + m.loadMixed() } else { - m = m.loadHome() + m.loadHome() } m.ready = true diff --git a/cmd/render.go b/cmd/render.go index 9790b4e..81ec350 100644 --- a/cmd/render.go +++ b/cmd/render.go @@ -8,7 +8,7 @@ import ( var htom = tomd.NewConverter("", true, nil) -func (m Model) loadReader() Model { +func (m *Model) loadReader() { id := m.table.Cursor() post := m.context.feed.Posts[id] post.ID = id @@ -28,6 +28,4 @@ func (m Model) loadReader() Model { log.Fatalf("could not render markdown: %v", err) } m.viewport.SetContent(out) - - return m } From 363b19f12aad44c564ff2f9def2e7519b94927e4 Mon Sep 17 00:00:00 2001 From: isabel Date: Wed, 3 Jul 2024 13:50:09 +0100 Subject: [PATCH 04/21] chore: misc cleanup --- cmd/keys.go | 2 -- cmd/load.go | 2 +- lib/helpers.go | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/cmd/keys.go b/cmd/keys.go index 4d2bc46..a03174f 100644 --- a/cmd/keys.go +++ b/cmd/keys.go @@ -180,8 +180,6 @@ func (m Model) handleKeys(msg tea.KeyMsg) (Model, tea.Cmd) { m.loadContent(m.table.Cursor()) m.table.Focus() m.filter.Blur() - - return m, nil } } diff --git a/cmd/load.go b/cmd/load.go index 1aba72f..d1adbce 100644 --- a/cmd/load.go +++ b/cmd/load.go @@ -59,7 +59,7 @@ func (m *Model) loadContent(id int) { columns := []table.Column{ {Title: "", Width: 2}, {Title: "Date", Width: 15}, - {Title: "Title", Width: m.table.Width() - 25}, + {Title: "Title", Width: m.table.Width() - 17}, } rows := []table.Row{} diff --git a/lib/helpers.go b/lib/helpers.go index a006bdf..6eaa068 100644 --- a/lib/helpers.go +++ b/lib/helpers.go @@ -106,7 +106,7 @@ func Max(a, b int) int { func ReadSymbol(read bool) string { if read { - return " " + return "" } return "•" } From 1e00748954bb8b184758f3032fa324c501948987 Mon Sep 17 00:00:00 2001 From: isabel Date: Thu, 4 Jul 2024 10:47:25 +0100 Subject: [PATCH 05/21] chore: go mod tidy --- go.sum | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/go.sum b/go.sum index 97d1ecc..3979483 100644 --- a/go.sum +++ b/go.sum @@ -20,22 +20,14 @@ github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuP github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/charmbracelet/bubbles v0.18.0 h1:PYv1A036luoBGroX6VWjQIE9Syf2Wby2oOl/39KLfy0= github.com/charmbracelet/bubbles v0.18.0/go.mod h1:08qhZhtIwzgrtBjAcJnij1t1H0ZRjwHyGsy6AL11PSw= -github.com/charmbracelet/bubbletea v0.26.3 h1:iXyGvI+FfOWqkB2V07m1DF3xxQijxjY2j8PqiXYqasg= -github.com/charmbracelet/bubbletea v0.26.3/go.mod h1:bpZHfDHTYJC5g+FBK+ptJRCQotRC+Dhh3AoMxa/2+3Q= -github.com/charmbracelet/bubbletea v0.26.4 h1:2gDkkzLZaTjMl/dQBpNVtnvcCxsh/FCkimep7FC9c40= -github.com/charmbracelet/bubbletea v0.26.4/go.mod h1:P+r+RRA5qtI1DOHNFn0otoNwB4rn+zNAzSj/EXz6xU0= github.com/charmbracelet/bubbletea v0.26.6 h1:zTCWSuST+3yZYZnVSvbXwKOPRSNZceVeqpzOLN2zq1s= github.com/charmbracelet/bubbletea v0.26.6/go.mod h1:dz8CWPlfCCGLFbBlTY4N7bjLiyOGDJEnd2Muu7pOWhk= github.com/charmbracelet/glamour v0.7.0 h1:2BtKGZ4iVJCDfMF229EzbeR1QRKLWztO9dMtjmqZSng= github.com/charmbracelet/glamour v0.7.0/go.mod h1:jUMh5MeihljJPQbJ/wf4ldw2+yBP59+ctV36jASy7ps= github.com/charmbracelet/lipgloss v0.11.0 h1:UoAcbQ6Qml8hDwSWs0Y1cB5TEQuZkDPH/ZqwWWYTG4g= github.com/charmbracelet/lipgloss v0.11.0/go.mod h1:1UdRTH9gYgpcdNN5oBtjbu/IzNKtzVtb7sqN1t9LNn8= -github.com/charmbracelet/x/ansi v0.1.1 h1:CGAduulr6egay/YVbGc8Hsu8deMg1xZ/bkaXTPi1JDk= -github.com/charmbracelet/x/ansi v0.1.1/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/charmbracelet/x/ansi v0.1.2 h1:6+LR39uG8DE6zAmbu023YlqjJHkYXDF1z36ZwzO4xZY= github.com/charmbracelet/x/ansi v0.1.2/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= -github.com/charmbracelet/x/input v0.1.1 h1:YDOJaTUKCqtGnq9PHzx3pkkl4pXDOANUHmhH3DqMtM4= -github.com/charmbracelet/x/input v0.1.1/go.mod h1:jvdTVUnNWj/RD6hjC4FsoB0SeZCJ2ZBkiuFP9zXvZI0= github.com/charmbracelet/x/input v0.1.2 h1:QJAZr33eOhDowkkEQ24rsJy4Llxlm+fRDf/cQrmqJa0= github.com/charmbracelet/x/input v0.1.2/go.mod h1:LGBim0maUY4Pitjn/4fHnuXb4KirU3DODsyuHuXdOyA= github.com/charmbracelet/x/term v0.1.1 h1:3cosVAiPOig+EV4X9U+3LDgtwwAoEzJjNdwbXDjF6yI= @@ -126,14 +118,10 @@ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavM github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= -github.com/yuin/goldmark v1.3.7/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yuin/goldmark v1.7.1 h1:3bajkSilaCbjdKVsKdZjZCLBNPL9pYzrCakKaf4U49U= github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg= github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= -github.com/yuin/goldmark-emoji v1.0.2 h1:c/RgTShNgHTtc6xdz2KKI74jJr6rWi7FPgnP9GAsO5s= -github.com/yuin/goldmark-emoji v1.0.2/go.mod h1:RhP/RWpexdp+KHs7ghKnifRoIs/Bq4nDS7tRbCkOwKY= github.com/yuin/goldmark-emoji v1.0.3 h1:aLRkLHOuBR2czCY4R8olwMjID+tENfhyFDMCRhbIQY4= github.com/yuin/goldmark-emoji v1.0.3/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -153,7 +141,6 @@ golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= @@ -175,7 +162,6 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= @@ -193,7 +179,6 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= From aac3b0dfbf9d36600710fb5e8654872935e84cab Mon Sep 17 00:00:00 2001 From: isabel Date: Thu, 4 Jul 2024 13:35:09 +0100 Subject: [PATCH 06/21] refactor: reduce help complexity if we are vendoring for custom changes we may as well go all out --- cmd/help.go | 59 ++++++++++------------------------------------------ cmd/modal.go | 10 +-------- 2 files changed, 12 insertions(+), 57 deletions(-) diff --git a/cmd/help.go b/cmd/help.go index 52a792f..1fffa01 100644 --- a/cmd/help.go +++ b/cmd/help.go @@ -9,6 +9,7 @@ import ( "github.com/charmbracelet/bubbles/key" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" + "github.com/isabelroses/izrss/lib" ) // KeyMap is a map of keybindings used to generate help. Since it's an @@ -29,24 +30,9 @@ type KeyMap interface { FullHelp(m Model) [][]key.Binding } -// Styles is a set of available style definitions for the Help bubble. -type Styles struct { - Ellipsis lipgloss.Style - - // Styling for the short help - ShortKey lipgloss.Style - ShortDesc lipgloss.Style - ShortSeparator lipgloss.Style - - // Styling for the full help - FullKey lipgloss.Style - FullDesc lipgloss.Style - FullSeparator lipgloss.Style -} - // KeyModel contains the state of the help view. type KeyModel struct { - Styles Styles + Style lipgloss.Style ShortSeparator string FullSeparator string Ellipsis string @@ -56,34 +42,11 @@ type KeyModel struct { // New creates a new help view with some useful defaults. func NewHelp() KeyModel { - keyStyle := lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{ - Light: "#909090", - Dark: "#626262", - }) - - descStyle := lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{ - Light: "#B2B2B2", - Dark: "#4A4A4A", - }) - - sepStyle := lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{ - Light: "#DDDADA", - Dark: "#3C3C3C", - }) - return KeyModel{ ShortSeparator: " • ", FullSeparator: " ", Ellipsis: "…", - Styles: Styles{ - ShortKey: keyStyle, - ShortDesc: descStyle, - ShortSeparator: sepStyle, - Ellipsis: sepStyle, - FullKey: keyStyle, - FullDesc: descStyle, - FullSeparator: sepStyle, - }, + Style: lib.HelpStyle, } } @@ -110,7 +73,7 @@ func (m KeyModel) ShortHelpView(bindings []key.Binding) string { var b strings.Builder var totalWidth int - separator := m.Styles.ShortSeparator.Inline(true).Render(m.ShortSeparator) + separator := m.Style.Inline(true).Render(m.ShortSeparator) for i, kb := range bindings { if !kb.Enabled() { @@ -123,8 +86,8 @@ func (m KeyModel) ShortHelpView(bindings []key.Binding) string { } str := sep + - m.Styles.ShortKey.Inline(true).Render(kb.Help().Key) + " " + - m.Styles.ShortDesc.Inline(true).Render(kb.Help().Desc) + m.Style.Inline(true).Render(kb.Help().Key) + " " + + m.Style.Inline(true).Render(kb.Help().Desc) w := lipgloss.Width(str) @@ -132,7 +95,7 @@ func (m KeyModel) ShortHelpView(bindings []key.Binding) string { // drawing. if m.Width > 0 && totalWidth+w > m.Width { // Although if there's room for an ellipsis, print that. - tail := " " + m.Styles.Ellipsis.Inline(true).Render(m.Ellipsis) + tail := " " + m.Style.Inline(true).Render(m.Ellipsis) tailWidth := lipgloss.Width(tail) if totalWidth+tailWidth < m.Width { @@ -163,7 +126,7 @@ func (m KeyModel) FullHelpView(groups [][]key.Binding) string { out []string totalWidth int - sep = m.Styles.FullSeparator.Render(m.FullSeparator) + sep = m.Style.Render(m.FullSeparator) sepWidth = lipgloss.Width(sep) ) @@ -188,9 +151,9 @@ func (m KeyModel) FullHelpView(groups [][]key.Binding) string { } col := lipgloss.JoinHorizontal(lipgloss.Top, - m.Styles.FullKey.Render(strings.Join(keys, "\n")), - m.Styles.FullKey.Render(" "), - m.Styles.FullDesc.Render(strings.Join(descriptions, "\n")), + m.Style.Render(strings.Join(keys, "\n")), + m.Style.Render(" "), + m.Style.Render(strings.Join(descriptions, "\n")), ) // Column diff --git a/cmd/modal.go b/cmd/modal.go index 67b8f0b..319d8b8 100644 --- a/cmd/modal.go +++ b/cmd/modal.go @@ -43,20 +43,12 @@ func NewModel() Model { Bold(true). Foreground(lipgloss.Color("229")) - h := NewHelp() - h.Styles.FullKey = lib.HelpStyle - h.Styles.FullDesc = lib.HelpStyle - h.Styles.FullSeparator = lib.HelpStyle - h.Styles.ShortKey = lib.HelpStyle - h.Styles.ShortDesc = lib.HelpStyle - h.Styles.ShortSeparator = lib.HelpStyle - return Model{ context: context{}, viewport: viewport.Model{}, table: t, ready: false, - help: h, + help: NewHelp(), keys: keys, filter: f, } From 23c422ff28ade8c6fa819131c86779ab0a8a65e7 Mon Sep 17 00:00:00 2001 From: isabel Date: Thu, 4 Jul 2024 14:35:35 +0100 Subject: [PATCH 07/21] refacotor: merge reader and main view styles --- cmd/context.go | 3 +++ cmd/help.go | 6 +++--- cmd/keys.go | 19 +++++++++++-------- cmd/render.go | 2 ++ cmd/view.go | 26 ++++++++------------------ 5 files changed, 27 insertions(+), 29 deletions(-) diff --git a/cmd/context.go b/cmd/context.go index 9888220..a31d144 100644 --- a/cmd/context.go +++ b/cmd/context.go @@ -15,4 +15,7 @@ type context struct { func (m *Model) swapPage(next string) { m.context.prev = m.context.curr m.context.curr = next + if m.context.prev == "reader" { + m.viewport.Height = m.viewport.Height + 2 + } } diff --git a/cmd/help.go b/cmd/help.go index 1fffa01..a7bb967 100644 --- a/cmd/help.go +++ b/cmd/help.go @@ -22,7 +22,7 @@ type KeyMap interface { // ShortHelp returns a slice of bindings to be displayed in the short // version of the help. The help bubble will render help in the order in // which the help items are returned here. - ShortHelp() []key.Binding + ShortHelp(m Model) []key.Binding // FullHelp returns an extended group of help items, grouped by columns. // The help bubble will render the help in the order in which the help @@ -44,7 +44,7 @@ type KeyModel struct { func NewHelp() KeyModel { return KeyModel{ ShortSeparator: " • ", - FullSeparator: " ", + FullSeparator: " • ", Ellipsis: "…", Style: lib.HelpStyle, } @@ -60,7 +60,7 @@ func (km KeyModel) View(k KeyMap, m Model) string { if km.ShowAll { return km.FullHelpView(k.FullHelp(m)) } - return km.ShortHelpView(k.ShortHelp()) + return km.ShortHelpView(k.ShortHelp(m)) } // ShortHelpView renders a single line help view from a slice of keybindings. diff --git a/cmd/keys.go b/cmd/keys.go index a03174f..2b4e9bd 100644 --- a/cmd/keys.go +++ b/cmd/keys.go @@ -25,8 +25,16 @@ type keyMap struct { ReadAll key.Binding } -func (k keyMap) ShortHelp() []key.Binding { - return []key.Binding{k.Help, k.Quit} +func (k keyMap) ShortHelp(m Model) []key.Binding { + var help []key.Binding + + if m.context.curr == "reader" { + help = []key.Binding{k.Open, k.ToggleRead, k.Quit} + } else { + help = []key.Binding{k.Help, k.Quit} + } + + return help } func (k keyMap) FullHelp(m Model) [][]key.Binding { @@ -52,12 +60,7 @@ func (k keyMap) FullHelp(m Model) [][]key.Binding { {k.Help, k.Quit}, } case "reader": - help = [][]key.Binding{ - {k.Up, k.Down}, - {k.Back, k.Open}, - {k.ToggleRead}, - {k.Help, k.Quit}, - } + help = [][]key.Binding{{k.Open}, {k.ToggleRead}, {k.Quit}} } return help diff --git a/cmd/render.go b/cmd/render.go index 81ec350..33131ec 100644 --- a/cmd/render.go +++ b/cmd/render.go @@ -27,5 +27,7 @@ func (m *Model) loadReader() { if err != nil { log.Fatalf("could not render markdown: %v", err) } + m.viewport.SetContent(out) + m.viewport.Height = m.viewport.Height - 2 } diff --git a/cmd/view.go b/cmd/view.go index cfd01e9..e12d423 100644 --- a/cmd/view.go +++ b/cmd/view.go @@ -2,24 +2,12 @@ package cmd import ( "fmt" - "strings" "github.com/charmbracelet/lipgloss" + "github.com/isabelroses/izrss/lib" ) -func (m Model) headerView() string { - title := lib.ReaderStyle.Render(m.context.post.Title) - line := strings.Repeat("─", lib.Max(0, m.viewport.Width-lipgloss.Width(title))) - return lipgloss.JoinHorizontal(lipgloss.Center, title, line) -} - -func (m Model) footerView() string { - info := lib.ReaderStyle.Render(fmt.Sprintf("%3.f%%", m.viewport.ScrollPercent()*100)) - line := strings.Repeat("─", lib.Max(0, m.viewport.Width-lipgloss.Width(info))) - return lipgloss.JoinHorizontal(lipgloss.Center, line, info) -} - // View renders the model as a string func (m Model) View() string { out := "" @@ -27,11 +15,13 @@ func (m Model) View() string { if !m.ready { out = "Initializing..." } else if m.context.curr == "reader" { - out = lipgloss.JoinVertical( - lipgloss.Top, - m.headerView(), - m.viewport.View(), - m.footerView(), + out = lib.MainStyle.Render( + lipgloss.JoinVertical( + lipgloss.Top, + fmt.Sprintf("%s - %3.f%%", m.context.post.Title, m.viewport.ScrollPercent()*100), + m.viewport.View(), + m.help.View(m.keys, m), + ), ) } else { out = lib.MainStyle.Render(m.viewport.View()) From 0763c6605685d714ae79e4a5d405962e766c0410 Mon Sep 17 00:00:00 2001 From: isabel Date: Thu, 4 Jul 2024 16:55:23 +0100 Subject: [PATCH 08/21] chore: cleanup --- lib/helpers.go | 8 -------- lib/style.go | 3 --- 2 files changed, 11 deletions(-) diff --git a/lib/helpers.go b/lib/helpers.go index 6eaa068..0aa674b 100644 --- a/lib/helpers.go +++ b/lib/helpers.go @@ -96,14 +96,6 @@ func URLToDir(url string) string { return url } -// Max returns the maximum of two integers -func Max(a, b int) int { - if a > b { - return a - } - return b -} - func ReadSymbol(read bool) string { if read { return "" diff --git a/lib/style.go b/lib/style.go index d2024cc..0dd4947 100644 --- a/lib/style.go +++ b/lib/style.go @@ -14,9 +14,6 @@ var ( Padding(0, 1). Margin(0) - // ReaderStyle is the style for the reader - ReaderStyle = lipgloss.NewStyle() - // HelpStyle is the style for the help keybinds menu HelpStyle = lipgloss.NewStyle().Foreground(lipgloss.Color(UserConfig.Colors.Subtext)) ) From ce064849da7f276dc5fcc61e60ef4e3e89c89f70 Mon Sep 17 00:00:00 2001 From: isabel Date: Thu, 4 Jul 2024 17:48:58 +0100 Subject: [PATCH 09/21] feat: handle mixed keys --- cmd/keys.go | 47 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/cmd/keys.go b/cmd/keys.go index 2b4e9bd..0b4b77d 100644 --- a/cmd/keys.go +++ b/cmd/keys.go @@ -45,9 +45,8 @@ func (k keyMap) FullHelp(m Model) [][]key.Binding { help = [][]key.Binding{ {k.Up, k.Down}, {k.Back, k.Open}, - {k.Search}, + {k.Search, k.ReadAll}, {k.Refresh, k.RefreshAll}, - {k.ReadAll}, {k.Help, k.Quit}, } case "content": @@ -59,6 +58,14 @@ func (k keyMap) FullHelp(m Model) [][]key.Binding { {k.ToggleRead, k.ReadAll}, {k.Help, k.Quit}, } + case "mixed": + help = [][]key.Binding{ + {k.Up, k.Down}, + {k.Back, k.Open}, + {k.Search, k.ToggleRead}, + // {k.Refresh, k.RefreshAll}, + {k.Help, k.Quit}, + } case "reader": help = [][]key.Binding{{k.Open}, {k.ToggleRead}, {k.Quit}} } @@ -144,10 +151,36 @@ func (m Model) handleKeys(msg tea.KeyMsg) (Model, tea.Cmd) { } } + case "mixed": + switch { + case key.Matches(msg, m.keys.Open): + m.loadReader() + + case key.Matches(msg, m.keys.ToggleRead): + lib.ToggleRead(m.context.feeds, m.context.feed.ID, m.table.Cursor()) + m.loadMixed() + err := m.context.feeds.WriteTracking() + if err != nil { + log.Fatalf("Could not write tracking data: %s", err) + } + + case key.Matches(msg, m.keys.ReadAll): + lib.ReadAll(m.context.feeds, m.context.feed.ID) + m.loadMixed() + err := m.context.feeds.WriteTracking() + if err != nil { + log.Fatalf("Could not write tracking data: %s", err) + } + } + case "reader": switch { case key.Matches(msg, m.keys.Back): - m.loadContent(m.context.feed.ID) + if m.context.prev == "mixed" { + m.loadMixed() + } else { + m.loadContent(m.context.feed.ID) + } m.table.SetCursor(m.context.post.ID) m.viewport.SetYOffset(0) @@ -164,14 +197,6 @@ func (m Model) handleKeys(msg tea.KeyMsg) (Model, tea.Cmd) { if err != nil { log.Fatalf("Could not write tracking data: %s", err) } - - case key.Matches(msg, m.keys.ReadAll): - // if we are in the reader view, fall back to the normal mark all as read - lib.ToggleRead(m.context.feeds, m.context.feed.ID, m.context.post.ID) - err := m.context.feeds.WriteTracking() - if err != nil { - log.Fatalf("Could not write tracking data: %s", err) - } } case "search": From 075577f8999eae86fbef5cf967b4b0b01fc80da8 Mon Sep 17 00:00:00 2001 From: isabel Date: Thu, 4 Jul 2024 17:49:11 +0100 Subject: [PATCH 10/21] fix: style the content table correctly --- cmd/load.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/load.go b/cmd/load.go index d1adbce..3fd5503 100644 --- a/cmd/load.go +++ b/cmd/load.go @@ -30,9 +30,9 @@ func (m *Model) loadHome() { func (m *Model) loadMixed() { columns := []table.Column{ + {Title: "", Width: 2}, {Title: "Date", Width: 15}, - {Title: "Read", Width: 10}, - {Title: "Title", Width: m.table.Width() - 25}, + {Title: "Title", Width: m.table.Width() - 17}, } posts := []lib.Post{} @@ -43,7 +43,7 @@ func (m *Model) loadMixed() { rows := []table.Row{} for _, post := range posts { read := lib.ReadSymbol(post.Read) - rows = append(rows, table.Row{post.Date, read, post.Title}) + rows = append(rows, table.Row{read, post.Date, post.Title}) } m.context.feed.Posts = posts From 7c189c94d7a743f6798b65a9e2a623503ad77b35 Mon Sep 17 00:00:00 2001 From: isabel Date: Thu, 4 Jul 2024 17:56:26 +0100 Subject: [PATCH 11/21] chore: move to unstable bubbles --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index ca3309a..502b2c4 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.22.1 require ( github.com/JohannesKaufmann/html-to-markdown v1.6.0 github.com/adrg/xdg v0.4.0 - github.com/charmbracelet/bubbles v0.18.0 + github.com/charmbracelet/bubbles v0.18.1-0.20240618201515-64a67d167062 github.com/charmbracelet/bubbletea v0.26.6 github.com/charmbracelet/lipgloss v0.11.0 github.com/mmcdole/gofeed v1.3.0 @@ -28,7 +28,7 @@ require ( github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/gorilla/css v1.0.1 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/microcosm-cc/bluemonday v1.0.26 // indirect + github.com/microcosm-cc/bluemonday v1.0.27 // indirect github.com/mmcdole/goxpp v1.1.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -54,6 +54,6 @@ require ( github.com/muesli/termenv v0.15.2 // indirect github.com/rivo/uniseg v0.4.7 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect ) diff --git a/go.sum b/go.sum index 3979483..211fb67 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,8 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= -github.com/charmbracelet/bubbles v0.18.0 h1:PYv1A036luoBGroX6VWjQIE9Syf2Wby2oOl/39KLfy0= -github.com/charmbracelet/bubbles v0.18.0/go.mod h1:08qhZhtIwzgrtBjAcJnij1t1H0ZRjwHyGsy6AL11PSw= +github.com/charmbracelet/bubbles v0.18.1-0.20240618201515-64a67d167062 h1:TXi5K9XRxEXPhsvvWZZZhZyF/547xx1Q+Ywjeop+w9Y= +github.com/charmbracelet/bubbles v0.18.1-0.20240618201515-64a67d167062/go.mod h1:z199e1Fc5JXB44at0N3xsoBgbQh2rFAFw35+F4/wv+8= github.com/charmbracelet/bubbletea v0.26.6 h1:zTCWSuST+3yZYZnVSvbXwKOPRSNZceVeqpzOLN2zq1s= github.com/charmbracelet/bubbletea v0.26.6/go.mod h1:dz8CWPlfCCGLFbBlTY4N7bjLiyOGDJEnd2Muu7pOWhk= github.com/charmbracelet/glamour v0.7.0 h1:2BtKGZ4iVJCDfMF229EzbeR1QRKLWztO9dMtjmqZSng= @@ -63,8 +63,8 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= -github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= +github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= +github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= github.com/mmcdole/gofeed v1.3.0 h1:5yn+HeqlcvjMeAI4gu6T+crm7d0anY85+M+v6fIFNG4= github.com/mmcdole/gofeed v1.3.0/go.mod h1:9TGv2LcJhdXePDzxiuMnukhV2/zb6VtnZt1mS+SjkLE= github.com/mmcdole/goxpp v1.1.1 h1:RGIX+D6iQRIunGHrKqnA2+700XMCnNv0bAOOv5MUhx8= @@ -163,8 +163,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= From 7b9f3daca0caf05231c2762cd9f3295b0232bc87 Mon Sep 17 00:00:00 2001 From: isabel Date: Thu, 4 Jul 2024 19:55:53 +0100 Subject: [PATCH 12/21] chore(nix): update hash --- nix/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/default.nix b/nix/default.nix index df0d46e..ef4abfd 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -19,7 +19,7 @@ buildGoModule { ] ); }; - vendorHash = "sha256-XYJuXEGHGYTeprHp9oBiHCrKBVc46KpYY3qqlEknr+8="; + vendorHash = "sha256-t2I7NwLiR4X9kxBiZFygz4cNF9L+lZUvrdWkR7Ev3Hc="; ldflags = [ "-s" From b56a06885f78041322283ed76fc8efd164fbd445 Mon Sep 17 00:00:00 2001 From: isabel Date: Thu, 18 Jul 2024 11:11:21 +0100 Subject: [PATCH 13/21] chore: bump deps --- go.mod | 10 +++++----- go.sum | 22 ++++++++++------------ nix/default.nix | 2 +- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 502b2c4..445f62d 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,10 @@ go 1.22.1 require ( github.com/JohannesKaufmann/html-to-markdown v1.6.0 - github.com/adrg/xdg v0.4.0 + github.com/adrg/xdg v0.5.0 github.com/charmbracelet/bubbles v0.18.1-0.20240618201515-64a67d167062 github.com/charmbracelet/bubbletea v0.26.6 - github.com/charmbracelet/lipgloss v0.11.0 + github.com/charmbracelet/lipgloss v0.12.1 github.com/mmcdole/gofeed v1.3.0 github.com/pelletier/go-toml/v2 v2.2.2 github.com/urfave/cli/v2 v2.27.2 @@ -19,12 +19,12 @@ require ( github.com/andybalholm/cascadia v1.3.2 // indirect github.com/atotto/clipboard v0.1.4 // indirect github.com/aymerick/douceur v0.2.0 // indirect - github.com/charmbracelet/x/ansi v0.1.2 // indirect + github.com/charmbracelet/x/ansi v0.1.4 // indirect github.com/charmbracelet/x/input v0.1.2 // indirect github.com/charmbracelet/x/term v0.1.1 // indirect github.com/charmbracelet/x/windows v0.1.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect - github.com/dlclark/regexp2 v1.11.0 // indirect + github.com/dlclark/regexp2 v1.11.2 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/gorilla/css v1.0.1 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -38,7 +38,7 @@ require ( github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect github.com/yuin/goldmark v1.7.4 // indirect github.com/yuin/goldmark-emoji v1.0.3 // indirect - golang.org/x/net v0.26.0 // indirect + golang.org/x/net v0.27.0 // indirect ) require ( diff --git a/go.sum b/go.sum index 211fb67..6c6bd39 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/JohannesKaufmann/html-to-markdown v1.6.0 h1:04VXMiE50YYfCfLboJCLcgqF5 github.com/JohannesKaufmann/html-to-markdown v1.6.0/go.mod h1:NUI78lGg/a7vpEJTz/0uOcYMaibytE4BUOQS8k78yPQ= github.com/PuerkitoBio/goquery v1.9.2 h1:4/wZksC3KgkQw7SQgkKotmKljk0M6V8TUvA8Wb4yPeE= github.com/PuerkitoBio/goquery v1.9.2/go.mod h1:GHPCaP0ODyyxqcNoFGYlAprUFH81NuRPd0GX3Zu2Mvk= -github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= -github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E= +github.com/adrg/xdg v0.5.0 h1:dDaZvhMXatArP1NPHhnfaQUqWBLBsmx1h1HXQdMoFCY= +github.com/adrg/xdg v0.5.0/go.mod h1:dDdY4M4DF9Rjy4kHPeNL+ilVF+p2lK8IdM9/rTSGcI4= github.com/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE= github.com/alecthomas/assert/v2 v2.7.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E= @@ -24,10 +24,10 @@ github.com/charmbracelet/bubbletea v0.26.6 h1:zTCWSuST+3yZYZnVSvbXwKOPRSNZceVeqp github.com/charmbracelet/bubbletea v0.26.6/go.mod h1:dz8CWPlfCCGLFbBlTY4N7bjLiyOGDJEnd2Muu7pOWhk= github.com/charmbracelet/glamour v0.7.0 h1:2BtKGZ4iVJCDfMF229EzbeR1QRKLWztO9dMtjmqZSng= github.com/charmbracelet/glamour v0.7.0/go.mod h1:jUMh5MeihljJPQbJ/wf4ldw2+yBP59+ctV36jASy7ps= -github.com/charmbracelet/lipgloss v0.11.0 h1:UoAcbQ6Qml8hDwSWs0Y1cB5TEQuZkDPH/ZqwWWYTG4g= -github.com/charmbracelet/lipgloss v0.11.0/go.mod h1:1UdRTH9gYgpcdNN5oBtjbu/IzNKtzVtb7sqN1t9LNn8= -github.com/charmbracelet/x/ansi v0.1.2 h1:6+LR39uG8DE6zAmbu023YlqjJHkYXDF1z36ZwzO4xZY= -github.com/charmbracelet/x/ansi v0.1.2/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/lipgloss v0.12.1 h1:/gmzszl+pedQpjCOH+wFkZr/N90Snz40J/NR7A0zQcs= +github.com/charmbracelet/lipgloss v0.12.1/go.mod h1:V2CiwIuhx9S1S1ZlADfOj9HmxeMAORuz5izHb0zGbB8= +github.com/charmbracelet/x/ansi v0.1.4 h1:IEU3D6+dWwPSgZ6HBH+v6oUuZ/nVawMiWj5831KfiLM= +github.com/charmbracelet/x/ansi v0.1.4/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/charmbracelet/x/input v0.1.2 h1:QJAZr33eOhDowkkEQ24rsJy4Llxlm+fRDf/cQrmqJa0= github.com/charmbracelet/x/input v0.1.2/go.mod h1:LGBim0maUY4Pitjn/4fHnuXb4KirU3DODsyuHuXdOyA= github.com/charmbracelet/x/term v0.1.1 h1:3cosVAiPOig+EV4X9U+3LDgtwwAoEzJjNdwbXDjF6yI= @@ -39,8 +39,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= -github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dlclark/regexp2 v1.11.2 h1:/u628IuisSTwri5/UKloiIsH8+qF2Pu7xEQX+yIKg68= +github.com/dlclark/regexp2 v1.11.2/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -106,7 +106,6 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= @@ -142,8 +141,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -153,7 +152,6 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/nix/default.nix b/nix/default.nix index ef4abfd..eb263b3 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -19,7 +19,7 @@ buildGoModule { ] ); }; - vendorHash = "sha256-t2I7NwLiR4X9kxBiZFygz4cNF9L+lZUvrdWkR7Ev3Hc="; + vendorHash = "sha256-I4M0X2H8kLjNS9zAFonnP6gtHVNX9Cy36D6CUc1sOfs="; ldflags = [ "-s" From 59977ee85e5533f10126e01b8d205b89d8fbd255 Mon Sep 17 00:00:00 2001 From: isabel Date: Thu, 18 Jul 2024 13:10:46 +0100 Subject: [PATCH 14/21] fix: help menu hight --- cmd/keys.go | 4 ++-- cmd/main.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/keys.go b/cmd/keys.go index 0b4b77d..d7c6814 100644 --- a/cmd/keys.go +++ b/cmd/keys.go @@ -67,7 +67,7 @@ func (k keyMap) FullHelp(m Model) [][]key.Binding { {k.Help, k.Quit}, } case "reader": - help = [][]key.Binding{{k.Open}, {k.ToggleRead}, {k.Quit}} + help = [][]key.Binding{} } return help @@ -220,7 +220,7 @@ func (m Model) handleKeys(msg tea.KeyMsg) (Model, tea.Cmd) { case key.Matches(msg, m.keys.Help): m.help.ShowAll = !m.help.ShowAll - m.table.SetHeight(m.viewport.Height - lipgloss.Height(m.help.View(m.keys, m)) - lib.MainStyle.GetBorderBottomSize()) + m.table.SetHeight(m.viewport.Height - lipgloss.Height(m.help.View(m.keys, m))) case key.Matches(msg, m.keys.Quit): err := m.context.feeds.WriteTracking() diff --git a/cmd/main.go b/cmd/main.go index c32de44..83117c4 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -39,7 +39,7 @@ func (m Model) handleWindowSize(msg tea.WindowSizeMsg) Model { width := msg.Width - framew m.table.SetWidth(width) - m.table.SetHeight(height - lipgloss.Height(m.help.View(m.keys, m)) - lib.MainStyle.GetBorderBottomSize()) + m.table.SetHeight(height - lipgloss.Height(m.help.View(m.keys, m))) if !m.ready { m.context.feeds = lib.GetAllContent(lib.UserConfig.Urls, lib.CheckCache()) From 662f8dfc5cea7cd4d76d941ef39d7e612d2d84fa Mon Sep 17 00:00:00 2001 From: isabel Date: Thu, 22 Aug 2024 12:14:58 +0100 Subject: [PATCH 15/21] chore: bump deps --- flake.lock | 6 ++-- go.mod | 33 ++++++++++------------ go.sum | 73 +++++++++++++++++++++++-------------------------- nix/default.nix | 2 +- 4 files changed, 53 insertions(+), 61 deletions(-) diff --git a/flake.lock b/flake.lock index 994aa44..618e92e 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1720957393, - "narHash": "sha256-oedh2RwpjEa+TNxhg5Je9Ch6d3W1NKi7DbRO1ziHemA=", + "lastModified": 1724224976, + "narHash": "sha256-Z/ELQhrSd7bMzTO8r7NZgi9g5emh+aRKoCdaAv5fiO0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "693bc46d169f5af9c992095736e82c3488bf7dbb", + "rev": "c374d94f1536013ca8e92341b540eba4c22f9c62", "type": "github" }, "original": { diff --git a/go.mod b/go.mod index 445f62d..d68931e 100644 --- a/go.mod +++ b/go.mod @@ -5,12 +5,12 @@ go 1.22.1 require ( github.com/JohannesKaufmann/html-to-markdown v1.6.0 github.com/adrg/xdg v0.5.0 - github.com/charmbracelet/bubbles v0.18.1-0.20240618201515-64a67d167062 - github.com/charmbracelet/bubbletea v0.26.6 - github.com/charmbracelet/lipgloss v0.12.1 + github.com/charmbracelet/bubbles v0.19.0 + github.com/charmbracelet/bubbletea v0.27.0 + github.com/charmbracelet/lipgloss v0.13.0 github.com/mmcdole/gofeed v1.3.0 github.com/pelletier/go-toml/v2 v2.2.2 - github.com/urfave/cli/v2 v2.27.2 + github.com/urfave/cli/v2 v2.27.4 ) require ( @@ -19,12 +19,10 @@ require ( github.com/andybalholm/cascadia v1.3.2 // indirect github.com/atotto/clipboard v0.1.4 // indirect github.com/aymerick/douceur v0.2.0 // indirect - github.com/charmbracelet/x/ansi v0.1.4 // indirect - github.com/charmbracelet/x/input v0.1.2 // indirect - github.com/charmbracelet/x/term v0.1.1 // indirect - github.com/charmbracelet/x/windows v0.1.2 // indirect + github.com/charmbracelet/x/ansi v0.2.3 // indirect + github.com/charmbracelet/x/term v0.2.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect - github.com/dlclark/regexp2 v1.11.2 // indirect + github.com/dlclark/regexp2 v1.11.4 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/gorilla/css v1.0.1 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -32,28 +30,27 @@ require ( github.com/mmcdole/goxpp v1.1.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect github.com/yuin/goldmark v1.7.4 // indirect github.com/yuin/goldmark-emoji v1.0.3 // indirect - golang.org/x/net v0.27.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/term v0.23.0 // indirect ) require ( github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect - github.com/charmbracelet/glamour v0.7.0 + github.com/charmbracelet/glamour v0.8.0 github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-localereader v0.0.1 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/reflow v0.3.0 // indirect - github.com/muesli/termenv v0.15.2 // indirect + github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect github.com/rivo/uniseg v0.4.7 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/text v0.17.0 // indirect ) diff --git a/go.sum b/go.sum index 6c6bd39..4ded8af 100644 --- a/go.sum +++ b/go.sum @@ -16,31 +16,31 @@ github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= +github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= +github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= -github.com/charmbracelet/bubbles v0.18.1-0.20240618201515-64a67d167062 h1:TXi5K9XRxEXPhsvvWZZZhZyF/547xx1Q+Ywjeop+w9Y= -github.com/charmbracelet/bubbles v0.18.1-0.20240618201515-64a67d167062/go.mod h1:z199e1Fc5JXB44at0N3xsoBgbQh2rFAFw35+F4/wv+8= -github.com/charmbracelet/bubbletea v0.26.6 h1:zTCWSuST+3yZYZnVSvbXwKOPRSNZceVeqpzOLN2zq1s= -github.com/charmbracelet/bubbletea v0.26.6/go.mod h1:dz8CWPlfCCGLFbBlTY4N7bjLiyOGDJEnd2Muu7pOWhk= -github.com/charmbracelet/glamour v0.7.0 h1:2BtKGZ4iVJCDfMF229EzbeR1QRKLWztO9dMtjmqZSng= -github.com/charmbracelet/glamour v0.7.0/go.mod h1:jUMh5MeihljJPQbJ/wf4ldw2+yBP59+ctV36jASy7ps= -github.com/charmbracelet/lipgloss v0.12.1 h1:/gmzszl+pedQpjCOH+wFkZr/N90Snz40J/NR7A0zQcs= -github.com/charmbracelet/lipgloss v0.12.1/go.mod h1:V2CiwIuhx9S1S1ZlADfOj9HmxeMAORuz5izHb0zGbB8= -github.com/charmbracelet/x/ansi v0.1.4 h1:IEU3D6+dWwPSgZ6HBH+v6oUuZ/nVawMiWj5831KfiLM= -github.com/charmbracelet/x/ansi v0.1.4/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= -github.com/charmbracelet/x/input v0.1.2 h1:QJAZr33eOhDowkkEQ24rsJy4Llxlm+fRDf/cQrmqJa0= -github.com/charmbracelet/x/input v0.1.2/go.mod h1:LGBim0maUY4Pitjn/4fHnuXb4KirU3DODsyuHuXdOyA= -github.com/charmbracelet/x/term v0.1.1 h1:3cosVAiPOig+EV4X9U+3LDgtwwAoEzJjNdwbXDjF6yI= -github.com/charmbracelet/x/term v0.1.1/go.mod h1:wB1fHt5ECsu3mXYusyzcngVWWlu1KKUmmLhfgr/Flxw= -github.com/charmbracelet/x/windows v0.1.2 h1:Iumiwq2G+BRmgoayww/qfcvof7W/3uLoelhxojXlRWg= -github.com/charmbracelet/x/windows v0.1.2/go.mod h1:GLEO/l+lizvFDBPLIOk+49gdX49L9YWMB5t+DZd0jkQ= +github.com/charmbracelet/bubbles v0.19.0 h1:gKZkKXPP6GlDk6EcfujDK19PCQqRjaJZQ7QRERx1UF0= +github.com/charmbracelet/bubbles v0.19.0/go.mod h1:WILteEqZ+krG5c3ntGEMeG99nCupcuIk7V0/zOP0tOA= +github.com/charmbracelet/bubbletea v0.27.0 h1:Mznj+vvYuYagD9Pn2mY7fuelGvP0HAXtZYGgRBCbHvU= +github.com/charmbracelet/bubbletea v0.27.0/go.mod h1:5MdP9XH6MbQkgGhnlxUqCNmBXf9I74KRQ8HIidRxV1Y= +github.com/charmbracelet/glamour v0.8.0 h1:tPrjL3aRcQbn++7t18wOpgLyl8wrOHUEDS7IZ68QtZs= +github.com/charmbracelet/glamour v0.8.0/go.mod h1:ViRgmKkf3u5S7uakt2czJ272WSg2ZenlYEZXT2x7Bjw= +github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw= +github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY= +github.com/charmbracelet/x/ansi v0.2.3 h1:VfFN0NUpcjBRd4DnKfRaIRo53KRgey/nhOoEqosGDEY= +github.com/charmbracelet/x/ansi v0.2.3/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b h1:MnAMdlwSltxJyULnrYbkZpp4k58Co7Tah3ciKhSNo0Q= +github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= +github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0= +github.com/charmbracelet/x/term v0.2.0/go.mod h1:GVxgxAbjUrmpvIINHIQnJJKpMlHiZ4cktEQCN6GWyF0= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dlclark/regexp2 v1.11.2 h1:/u628IuisSTwri5/UKloiIsH8+qF2Pu7xEQX+yIKg68= -github.com/dlclark/regexp2 v1.11.2/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo= +github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -59,10 +59,9 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= github.com/mmcdole/gofeed v1.3.0 h1:5yn+HeqlcvjMeAI4gu6T+crm7d0anY85+M+v6fIFNG4= @@ -80,10 +79,8 @@ github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELU github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= -github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= -github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a h1:2MaM6YC3mGu54x+RKAA6JiFFHlHDY1UbkxqppT7wYOg= +github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a/go.mod h1:hxSnBBYLK21Vtq/PHd0S2FYCxBXzBua8ov5s1RobyRQ= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -111,10 +108,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI= -github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM= -github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= -github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= +github.com/urfave/cli/v2 v2.27.4 h1:o1owoI+02Eb+K107p27wEX9Bb8eqIoZCfLXloLUSWJ8= +github.com/urfave/cli/v2 v2.27.4/go.mod h1:m4QzxcD2qpra4z7WhzEGn74WZLViBnMpb1ToCAKdGRQ= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -128,8 +123,6 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E= -golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -141,13 +134,13 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -161,8 +154,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -171,6 +164,8 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -178,8 +173,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= diff --git a/nix/default.nix b/nix/default.nix index eb263b3..a113b01 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -19,7 +19,7 @@ buildGoModule { ] ); }; - vendorHash = "sha256-I4M0X2H8kLjNS9zAFonnP6gtHVNX9Cy36D6CUc1sOfs="; + vendorHash = "sha256-K7rP6Cy4e2vzH1HLGfW0KZy/bLOlb2Thy5QQXDpijz8="; ldflags = [ "-s" From 4081b1b875a174510393cc110c22fc98f0f4b630 Mon Sep 17 00:00:00 2001 From: isabel Date: Thu, 22 Aug 2024 12:32:16 +0100 Subject: [PATCH 16/21] feat: table jumping --- cmd/keys.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/cmd/keys.go b/cmd/keys.go index d7c6814..da4cfbf 100644 --- a/cmd/keys.go +++ b/cmd/keys.go @@ -14,6 +14,8 @@ import ( type keyMap struct { Up key.Binding Down key.Binding + JumpUp key.Binding + JumpDown key.Binding Back key.Binding Help key.Binding Quit key.Binding @@ -44,6 +46,7 @@ func (k keyMap) FullHelp(m Model) [][]key.Binding { case "home": help = [][]key.Binding{ {k.Up, k.Down}, + {k.JumpUp, k.JumpDown}, {k.Back, k.Open}, {k.Search, k.ReadAll}, {k.Refresh, k.RefreshAll}, @@ -52,6 +55,7 @@ func (k keyMap) FullHelp(m Model) [][]key.Binding { case "content": help = [][]key.Binding{ {k.Up, k.Down}, + {k.JumpUp, k.JumpDown}, {k.Back, k.Open}, {k.Search}, {k.Refresh, k.RefreshAll}, @@ -61,6 +65,7 @@ func (k keyMap) FullHelp(m Model) [][]key.Binding { case "mixed": help = [][]key.Binding{ {k.Up, k.Down}, + {k.JumpUp, k.JumpDown}, {k.Back, k.Open}, {k.Search, k.ToggleRead}, // {k.Refresh, k.RefreshAll}, @@ -213,6 +218,11 @@ func (m Model) handleKeys(msg tea.KeyMsg) (Model, tea.Cmd) { // handle global keys switch { + case key.Matches(msg, m.keys.JumpUp): + m.table.MoveUp(5) + case key.Matches(msg, m.keys.JumpDown): + m.table.MoveDown(5) + case key.Matches(msg, m.keys.Search): if m.context.curr != "search" { m.loadSearch() @@ -242,6 +252,14 @@ var keys = keyMap{ key.WithKeys("down", "j"), key.WithHelp("↓/j", "move down"), ), + JumpUp: key.NewBinding( + key.WithKeys("shift+up", "K"), + key.WithHelp("↑/k", "jump move up"), + ), + JumpDown: key.NewBinding( + key.WithKeys("shift+down", "J"), + key.WithHelp("↓/j", "jump move down"), + ), Back: key.NewBinding( key.WithKeys("left", "h", "shift+tab"), key.WithHelp("←/h", "back"), From 95e6e03a0588c4d067f4fbb50cd8f9f65dab5459 Mon Sep 17 00:00:00 2001 From: isabel Date: Thu, 22 Aug 2024 13:14:48 +0100 Subject: [PATCH 17/21] refactor: speedup izrss entry --- cmd/main.go | 50 +++++++++++++++++++++++++++++--------------------- lib/feeds.go | 15 +++++++-------- 2 files changed, 36 insertions(+), 29 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index 83117c4..44074d1 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -2,6 +2,7 @@ package cmd import ( "log" + "sync" "github.com/charmbracelet/bubbles/viewport" tea "github.com/charmbracelet/bubbletea" @@ -51,28 +52,34 @@ func (m Model) handleWindowSize(msg tea.WindowSizeMsg) Model { log.Fatalf("could not read tracking file: %v", err) } - var glamWidth glamour.TermRendererOption - switch lib.UserConfig.Reader.Size.(type) { - case string: - switch lib.UserConfig.Reader.Size { - case "full", "fullscreen": - glamWidth = glamour.WithWordWrap(width) - case "most": - glamWidth = glamour.WithWordWrap(int(float64(width) * 0.75)) - case "recomended": - glamWidth = glamour.WithWordWrap(80) + // we make this part mutli-threaded otherwise its really slow + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + var glamWidth glamour.TermRendererOption + switch lib.UserConfig.Reader.Size.(type) { + case string: + switch lib.UserConfig.Reader.Size { + case "full", "fullscreen": + glamWidth = glamour.WithWordWrap(width) + case "most": + glamWidth = glamour.WithWordWrap(int(float64(width) * 0.75)) + case "recomended": + glamWidth = glamour.WithWordWrap(80) + } + + case int64: + w := int(lib.UserConfig.Reader.Size.(int64)) + glamWidth = glamour.WithWordWrap(w) + default: + log.Fatalf("invalid reader size: %v", lib.UserConfig.Reader.Size) } - - case int64: - w := int(lib.UserConfig.Reader.Size.(int64)) - glamWidth = glamour.WithWordWrap(w) - default: - log.Fatalf("invalid reader size: %v", lib.UserConfig.Reader.Size) - } - m.glam, _ = glamour.NewTermRenderer( - glamour.WithEnvironmentConfig(), - glamWidth, - ) + m.glam, _ = glamour.NewTermRenderer( + glamour.WithEnvironmentConfig(), + glamWidth, + ) + }() if lib.UserConfig.Home == "mixed" { m.loadMixed() @@ -80,6 +87,7 @@ func (m Model) handleWindowSize(msg tea.WindowSizeMsg) Model { m.loadHome() } + wg.Wait() m.ready = true } else { m.viewport.Width = width diff --git a/lib/feeds.go b/lib/feeds.go index e1e77ae..bb90d86 100644 --- a/lib/feeds.go +++ b/lib/feeds.go @@ -54,22 +54,21 @@ func (f Feed) GetTotalUnreads() int { // also a bit of nix inspired me to write this `foldl recursiveUpdate { } importedLibs` // okay maybe it was beacuse of the comments not actually the code, kinda fair. func mergeFeeds(feeds1, feeds2 Feeds) Feeds { - // Create a map to hold posts from feeds1 by their UUID for quick lookup - postMap := make(map[string]*Post) + // Create a map to hold posts' read state from feeds1 by their UUID for quick lookup + readStatusMap := make(map[string]bool) // Iterate through feeds1 and map their posts by UUID - for i := range feeds1 { - for j := range feeds1[i].Posts { - postMap[feeds1[i].Posts[j].UUID] = &feeds1[i].Posts[j] + for _, feed := range feeds1 { + for _, post := range feed.Posts { + readStatusMap[post.UUID] = post.Read } } // Iterate through feeds2 and merge their posts into feeds1 based on UUID for i := range feeds2 { for j := range feeds2[i].Posts { - if post1, exists := postMap[feeds2[i].Posts[j].UUID]; exists { - // Update the existing post in feeds1 with the one from feeds2 - post1.Read = feeds2[i].Posts[j].Read + if readStatus, exists := readStatusMap[feeds1[i].Posts[j].UUID]; exists { + feeds1[i].Posts[j].Read = readStatus } } } From ac14666c84568728a11764e310a6d5f392048cce Mon Sep 17 00:00:00 2001 From: isabel Date: Thu, 22 Aug 2024 13:55:49 +0100 Subject: [PATCH 18/21] feat: theme reader settings --- cmd/main.go | 12 +++++++++++- lib/config.go | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/cmd/main.go b/cmd/main.go index 44074d1..7bd6371 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -75,8 +75,18 @@ func (m Model) handleWindowSize(msg tea.WindowSizeMsg) Model { default: log.Fatalf("invalid reader size: %v", lib.UserConfig.Reader.Size) } + + var glamTheme glamour.TermRendererOption + if lib.UserConfig.Reader.Theme == "environment" { + glamTheme = glamour.WithEnvironmentConfig() + } else if lib.UserConfig.Reader.Theme != "" { + glamTheme = glamour.WithStylePath(lib.UserConfig.Reader.Theme) + } else { + glamTheme = glamour.WithAutoStyle() + } + m.glam, _ = glamour.NewTermRenderer( - glamour.WithEnvironmentConfig(), + glamTheme, glamWidth, ) }() diff --git a/lib/config.go b/lib/config.go index 8ae44ab..e176fb4 100644 --- a/lib/config.go +++ b/lib/config.go @@ -38,6 +38,7 @@ var UserConfig = config{ Reader: reader{ Size: "recomended", ReadThreshold: 0.8, + Theme: "dark", }, Colors: colors{ Text: "#cdd6f4", @@ -67,5 +68,6 @@ type colors struct { type reader struct { Size interface{} `toml:"size"` + Theme string `toml:"theme"` ReadThreshold float64 `toml:"read_threshold"` } From 8fdaf0ec897020157781190ef8287d48e6c0d38c Mon Sep 17 00:00:00 2001 From: isabel Date: Thu, 22 Aug 2024 20:56:48 +0100 Subject: [PATCH 19/21] feat: sort posts in mixed view --- cmd/load.go | 8 +++++++- lib/feeds.go | 25 ++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/cmd/load.go b/cmd/load.go index 3fd5503..f72a5ab 100644 --- a/cmd/load.go +++ b/cmd/load.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "log" "strconv" "strings" @@ -40,13 +41,18 @@ func (m *Model) loadMixed() { posts = append(posts, feed.Posts...) } + err := lib.SortPosts(posts) + if err != nil { + log.Printf("Failed to sort %s", err) + } + rows := []table.Row{} for _, post := range posts { read := lib.ReadSymbol(post.Read) rows = append(rows, table.Row{read, post.Date, post.Title}) } - m.context.feed.Posts = posts + m.context.feed = lib.Feed{Title: "Mixed", Posts: posts, ID: 0, URL: ""} m.loadNewTable(columns, rows) m.swapPage("mixed") diff --git a/lib/feeds.go b/lib/feeds.go index bb90d86..e680e6d 100644 --- a/lib/feeds.go +++ b/lib/feeds.go @@ -1,6 +1,9 @@ package lib -import "sort" +import ( + "sort" + "time" +) // Post represents a single post in a feed type Post struct { @@ -75,3 +78,23 @@ func mergeFeeds(feeds1, feeds2 Feeds) Feeds { return feeds1 } + +// SortPostsByDate sorts an array of Post structs by the Date field. +func SortPosts(posts []Post) error { + dateFormat := UserConfig.DateFormat + + sort.Slice(posts, func(i, j int) bool { + // Parse the dates for the current comparison + dateI, errI := time.Parse(dateFormat, posts[i].Date) + dateJ, errJ := time.Parse(dateFormat, posts[j].Date) + + if errI != nil || errJ != nil { + return false + } + + // Compare the parsed dates + return dateI.After(dateJ) + }) + + return nil +} From 8ac10d912c346d4bb50367af51492c9d780e880f Mon Sep 17 00:00:00 2001 From: isabel Date: Thu, 22 Aug 2024 21:46:53 +0100 Subject: [PATCH 20/21] chore: reduce load profile --- cmd/load.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/load.go b/cmd/load.go index f72a5ab..f53a988 100644 --- a/cmd/load.go +++ b/cmd/load.go @@ -46,10 +46,10 @@ func (m *Model) loadMixed() { log.Printf("Failed to sort %s", err) } - rows := []table.Row{} - for _, post := range posts { + rows := make([]table.Row, len(posts)) + for i, post := range posts { read := lib.ReadSymbol(post.Read) - rows = append(rows, table.Row{read, post.Date, post.Title}) + rows[i] = table.Row{read, post.Date, post.Title} } m.context.feed = lib.Feed{Title: "Mixed", Posts: posts, ID: 0, URL: ""} From 743fb662293772dedb6b2e7bbdbaeac6ad388d89 Mon Sep 17 00:00:00 2001 From: isabel Date: Thu, 22 Aug 2024 21:47:31 +0100 Subject: [PATCH 21/21] fix: prevent mixed view crash with a hack --- cmd/main.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/main.go b/cmd/main.go index 7bd6371..0a5eeed 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -139,7 +139,8 @@ func (m Model) updateViewport(msg tea.Msg) (Model, tea.Cmd) { m.viewport.SetContent(view) } - if m.context.curr == "reader" && m.viewport.ScrollPercent() >= lib.UserConfig.Reader.ReadThreshold { + // HACK: if the previous was mixed we never marked the post as read + if m.context.curr == "reader" && m.context.prev == "mixed" && m.viewport.ScrollPercent() >= lib.UserConfig.Reader.ReadThreshold { lib.MarkRead(m.context.feeds, m.context.feed.ID, m.context.post.ID) }