Pad/internal/browser/handlers.go
Greg Pomerantz be123cf48d Fix redundant file loading and buffer insertion bugs
- Fix ChunkedBuffer.Insert to always update file length.
- Fix UpdateLineIndexAfterEdit to not shift the first line offset.
- Remove redundant ReadFileTask dispatch in HandleBrowserTap.
- Add end-to-end test for typing at start of buffer.
2026-06-05 10:45:48 -04:00

105 lines
2.8 KiB
Go

package browser
import (
"fmt"
"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
}
}
// resolveTapIndex maps a ListView row index to the actual sorted entry index.
// When search is active, the row index is into SearchResults, so we must
// look through SearchResults to find the real entry index.
func resolveTapIndex(s *BrowserState, index int) int {
if s.Query != "" && len(s.SearchResults) > 0 {
if index < 0 || index >= len(s.SearchResults) {
return -1
}
return s.SearchResults[index]
}
return index
}
// HandleBrowserTap processes a tap on the ListView at the given index.
func HandleBrowserTap(bm *BrowserManager, s *BrowserState, index int) {
// Resolve the ListView row index to the actual sorted entry index.
// When search is active, the row is an index into SearchResults.
entryIndex := resolveTapIndex(s, index)
if entryIndex < 0 || entryIndex >= s.TotalEntries {
return
}
entry, ok := getEntryByIndex(s, entryIndex)
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 = entryIndex
fmt.Printf("HandleBrowserTap: Opening file %s\n", entry.Path)
if ui.OpenFile != nil {
ui.OpenFile(entry.Path)
}
// Dispatch ReadFileTask to the worker pool
// task := pool.NewReadFileTask(entry.Path, bm.fs)
// fmt.Printf("HandleBrowserTap: Dispatching ReadFileTask for %s\n", entry.Path)
// bm.workerPool.Dispatch(task)
}
}