A minimal email TUI where you read with Markdown and write in Neovim. neomd.ssp.sh/docs
email markdown neovim tui
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

add bulkthreashold configurable

sspaeti 4bdc1290 6f7f859c

+24 -17
+1
docs/configuration.md
··· 52 52 inbox_count = 50 53 53 auto_screen_on_load = true # screen inbox automatically on every load (default true) 54 54 bg_sync_interval = 5 # background sync interval in minutes; 0 = disabled (default 5) 55 + bulk_progress_threshold = 10 # show progress counter for batch operations larger than this (default 10) 55 56 signature = """**Your Name** 56 57 Your Title, Your Company 57 58
+14 -5
internal/config/config.go
··· 101 101 102 102 // UIConfig holds display preferences. 103 103 type UIConfig struct { 104 - Theme string `toml:"theme"` // dark | light | auto 105 - InboxCount int `toml:"inbox_count"` // number of messages to fetch 106 - Signature string `toml:"signature"` // appended to new compose buffers (markdown) 107 - AutoScreenOnLoad *bool `toml:"auto_screen_on_load"` // screen inbox on every load (default true) 108 - BgSyncInterval int `toml:"bg_sync_interval"` // background sync interval in minutes (0 = disabled, default 5) 104 + Theme string `toml:"theme"` // dark | light | auto 105 + InboxCount int `toml:"inbox_count"` // number of messages to fetch 106 + Signature string `toml:"signature"` // appended to new compose buffers (markdown) 107 + AutoScreenOnLoad *bool `toml:"auto_screen_on_load"` // screen inbox on every load (default true) 108 + BgSyncInterval int `toml:"bg_sync_interval"` // background sync interval in minutes (0 = disabled, default 5) 109 + BulkProgressThreshold int `toml:"bulk_progress_threshold"` // show progress counter for batches larger than this (default 10) 110 + } 111 + 112 + // BulkThreshold returns the configured bulk progress threshold (default 10). 113 + func (u UIConfig) BulkThreshold() int { 114 + if u.BulkProgressThreshold <= 0 { 115 + return 10 116 + } 117 + return u.BulkProgressThreshold 109 118 } 110 119 111 120 // AutoScreen returns true if auto-screen-on-inbox-load is enabled (default: true).
+9 -12
internal/ui/model.go
··· 108 108 109 109 const maxUndoStack = 20 110 110 111 - // bulkProgressThreshold: only show progress for batches larger than this. 112 - const bulkProgressThreshold = 10 113 - 114 - func newBulkOp(label string, total int) *bulkOp { 115 - if total <= bulkProgressThreshold { 111 + func (m Model) newBulkOp(label string, total int) *bulkOp { 112 + if total <= m.cfg.UI.BulkThreshold() { 116 113 return nil // small batches don't need progress tracking 117 114 } 118 115 return &bulkOp{label: label, total: int64(total)} ··· 127 124 128 125 // startBulk initializes a bulk progress tracker. Call before launching batch commands. 129 126 func (m *Model) startBulk(label string, total int) { 130 - m.bulkProgress = newBulkOp(label, total) 127 + m.bulkProgress = m.newBulkOp(label, total) 131 128 } 132 129 133 130 // Version is set by main.go at startup (from build-time ldflags). ··· 1114 1111 if msg.folder == m.cfg.Folders.Inbox && m.cfg.UI.AutoScreen() && !m.screener.IsEmpty() { 1115 1112 if moves := m.previewAutoScreen(); len(moves) > 0 { 1116 1113 m.loading = true 1117 - m.bulkProgress = newBulkOp("Screening", len(moves)) 1114 + m.bulkProgress = m.newBulkOp("Screening", len(moves)) 1118 1115 return m, tea.Batch(sortCmd, m.fetchFolderCountsCmd(), m.spinner.Tick, m.execAutoScreenCmd(moves)) 1119 1116 } 1120 1117 } ··· 1665 1662 return m, nil 1666 1663 } 1667 1664 m.loading = true 1668 - m.bulkProgress = newBulkOp("Deleting", len(targets)) 1665 + m.bulkProgress = m.newBulkOp("Deleting", len(targets)) 1669 1666 return m, tea.Batch(m.spinner.Tick, m.batchMoveCmd(targets, m.cfg.Folders.Trash)) 1670 1667 1671 1668 case "X": // permanent delete (marked or cursor) — only in Trash ··· 1706 1703 return m, nil 1707 1704 } 1708 1705 m.loading = true 1709 - m.bulkProgress = newBulkOp("Screening", len(targets)) 1706 + m.bulkProgress = m.newBulkOp("Screening", len(targets)) 1710 1707 return m, tea.Batch(m.spinner.Tick, m.batchScreenerCmd(targets, key)) 1711 1708 1712 1709 // A = archive (pure move, no screener update) ··· 1716 1713 return m, nil 1717 1714 } 1718 1715 m.loading = true 1719 - m.bulkProgress = newBulkOp("Archiving", len(targets)) 1716 + m.bulkProgress = m.newBulkOp("Archiving", len(targets)) 1720 1717 return m, tea.Batch(m.spinner.Tick, m.batchMoveCmd(targets, m.cfg.Folders.Archive)) 1721 1718 1722 1719 // ── Auto-screen dry-run (Inbox only) ──────────────────────────── ··· 1768 1765 moves := m.pendingMoves 1769 1766 m.pendingMoves = nil 1770 1767 m.loading = true 1771 - m.bulkProgress = newBulkOp("Screening", len(moves)) 1768 + m.bulkProgress = m.newBulkOp("Screening", len(moves)) 1772 1769 return m, tea.Batch(m.spinner.Tick, m.execAutoScreenCmd(moves)) 1773 1770 1774 1771 case "n": ··· 2077 2074 } 2078 2075 if dst, ok := dstMap[key]; ok { 2079 2076 m.loading = true 2080 - m.bulkProgress = newBulkOp("Moving", len(targets)) 2077 + m.bulkProgress = m.newBulkOp("Moving", len(targets)) 2081 2078 return m, tea.Batch(m.spinner.Tick, m.batchMoveCmd(targets, dst)) 2082 2079 } 2083 2080 m.status = fmt.Sprintf("unknown: M%s", key)