package browser import ( "path/filepath" "strings" "pad/internal/ui" ) // HandleScroll updates the browser scroll index by the given delta (in entries). // Clamps to valid bounds and triggers prefetch/eviction as needed. func HandleScroll(s *BrowserState, delta int) { deltaPx := int(float64(delta) * s.EntryHeight) HandlePixelScroll(s, deltaPx) } // HandlePixelScroll updates the browser scroll offset by the given delta (in pixels). // Clamps to valid bounds and triggers eviction as needed. func HandlePixelScroll(s *BrowserState, delta int) { s.ScrollOffset += float64(delta) // Clamp to valid bounds clampScrollOffset(s) // Trigger eviction of distant pages s.EvictPages() } // clampScrollOffset ensures the scroll offset stays within valid bounds. func clampScrollOffset(s *BrowserState) { if s.ScrollOffset < 0 { s.ScrollOffset = 0 } // Use search results count if active, otherwise use TotalEntries entryCount := s.TotalEntries if s.Query != "" { entryCount = len(s.SearchResults) } // Calculate maximum scroll offset maxScroll := 0.0 if entryCount > s.VisibleCount { maxScroll = float64(entryCount-s.VisibleCount) * s.EntryHeight } if s.ScrollOffset > maxScroll { s.ScrollOffset = maxScroll } } // HandleBrowserTap processes a tap on the ListView at the given index. func HandleBrowserTap(bm *BrowserManager, s *BrowserState, index int) { if index < 0 || index >= s.TotalEntries { return } entry, ok := getEntryByIndex(s, index) if !ok { return // Page not loaded } if entry.IsDir { // Navigate into directory or up var newPath string if entry.Name == ".." { newPath = filepath.Dir(s.CurrentPath) } else { newPath = filepath.Join(s.CurrentPath, entry.Name) if !strings.HasPrefix(newPath, "/") { newPath = "/" + newPath } } bm.NavigateTo(newPath) } else { // Open file s.SelectedIndex = index ui.OpenFile(entry.Path) } }