Pad/internal/browser/browser.go
Greg Pomerantz 06b1444207 gofmt: format all remaining files with the go1.27 toolchain
The tree was formatted with an older gofmt; go1.27's gofmt additionally
wants: EOF exactly one newline (no trailing blank lines), imports sorted
alphabetically within a block, mixed-precedence binary expressions
re-spaced for grouping ((a+b)/c), single-field composite literals
un-aligned, adjacent one-line method signatures aligned, and one-line
bodies containing a compound statement expanded. Applied repo-wide
(31 files under internal/); pure formatting, no semantic changes —
build and the full test suite pass.
2026-08-23 10:03:27 -04:00

167 lines
4.3 KiB
Go

package browser
import (
"strings"
)
// LoadInitialPages loads the pages required for the current viewport from the
// SortIndex into the Pages map. This should be called after the SortIndex is built
// or updated.
func LoadInitialPages(s *BrowserState) {
if s.SortIndex == nil || s.TotalEntries == 0 {
return
}
// Calculate the range of pages to load (visible + prefetch)
minPage, maxPage := computeVisiblePageRange(s)
for i := minPage; i <= maxPage; i++ {
if _, ok := s.Pages[i]; !ok {
page := loadPageFromIndex(s, i)
if page != nil {
s.Pages[i] = page
}
}
}
}
// loadPageFromIndex creates a Page from the sorted index at the given page index.
// Uses position maps to convert sorted indices to raw indices for entry lookup.
// Returns nil if the page index is out of bounds.
func loadPageFromIndex(s *BrowserState, pageIndex int) *Page {
if pageIndex < 0 || pageIndex*PageSize >= s.TotalEntries {
return nil
}
if s.SortIndex == nil || len(s.SortIndex.Entries) == 0 {
return nil
}
start := pageIndex * PageSize
end := start + PageSize
if end > s.TotalEntries {
end = s.TotalEntries
}
// Get the position map for the current sort mode
positionMap := s.getSortedIndices()
if positionMap == nil {
return nil
}
// Build page entries using sorted order
entries := make([]Entry, 0, end-start)
for i := start; i < end; i++ {
rawIdx := positionMap[i]
entries = append(entries, s.SortIndex.Entries[rawIdx])
}
return NewPage(pageIndex, entries)
}
// computeVisiblePageRange returns the min and max page indices that should
// be loaded based on the current scroll position and visible count.
func computeVisiblePageRange(s *BrowserState) (minPage, maxPage int) {
minPage = s.GetScrollIndex()/PageSize - PrefetchDist
if minPage < 0 {
minPage = 0
}
maxPage = (s.GetScrollIndex()+s.VisibleCount)/PageSize + PrefetchDist
return minPage, maxPage
}
// getEntryByIndex returns the entry at the given sorted index, or nil if the page
// containing that entry is not loaded. Uses position maps to convert sorted
// indices to raw indices for correct sort order.
func getEntryByIndex(s *BrowserState, sortedIndex int) (*Entry, bool) {
if sortedIndex < 0 || sortedIndex >= s.TotalEntries {
return nil, false
}
pageIndex := sortedIndex / PageSize
page, ok := s.Pages[pageIndex]
if !ok || !page.Loaded {
return nil, false
}
offset := sortedIndex % PageSize
if offset >= len(page.Entries) {
return nil, false
}
return &page.Entries[offset], true
}
// GetSortedIndices is exported for testing purposes.
func (s *BrowserState) GetSortedIndices() []int {
return s.getSortedIndices()
}
// getSortedIndices returns the position map for the current sort mode.
// Returns nil if no sort index is available.
func (s *BrowserState) getSortedIndices() []int {
if s.SortIndex == nil || s.SortIndex.SortOrders == nil {
return nil
}
key := sortModeKey(s.SortMode)
return s.SortIndex.SortOrders[key]
}
// needsPrefetch determines if a page should be prefetched based on the
// current scroll position and visible count.
// Returns (true, pagesNeeded) if prefetch is needed.
func needsPrefetch(s *BrowserState, pageIndex int) (bool, int) {
minPage, maxPage := computeVisiblePageRange(s)
if pageIndex >= minPage && pageIndex <= maxPage {
if page, ok := s.Pages[pageIndex]; !ok || !page.Loaded {
return true, 1
}
}
return false, 0
}
// navigateToDirectory resets browser state and sets the new current path.
func navigateToDirectory(s *BrowserState, path string) {
s.CurrentPath = path
s.ScrollOffset = 0
s.SelectedIndex = -1
s.Pages = make(map[int]*Page)
s.SearchResults = nil
s.Query = ""
s.TotalEntries = 0
}
// computeTotalPages returns the total number of pages for the current entry count.
func computeTotalPages(s *BrowserState) int {
if s.TotalEntries == 0 {
return 0
}
pages := s.TotalEntries / PageSize
if s.TotalEntries%PageSize != 0 {
pages++
}
return pages
}
// filterEntriesByQuery returns indices of entries matching the query (case-insensitive).
// Returns nil for empty query.
func filterEntriesByQuery(entries []Entry, query string) []int {
if query == "" {
return nil
}
queryLower := strings.ToLower(query)
var results []int
for i, e := range entries {
if strings.Contains(strings.ToLower(e.Name), queryLower) {
results = append(results, i)
}
}
return results
}