@@ -718,19 +718,25 @@ impl App {
718718 self . config . prefetch_count
719719 }
720720
721- /// Prefetch adjacent images (next and previous) into the render cache.
721+ /// Prefetch adjacent images/pages into the render cache.
722722 /// Call this after the current image is fully displayed.
723723 pub fn prefetch_adjacent ( & mut self , terminal_size : Rect ) {
724724 // Skip if there's already a pending request (don't overwhelm the worker)
725725 if self . pending_request . is_some ( ) {
726726 return ;
727727 }
728-
729- let prefetch_count = self . prefetch_count ( ) ;
730- if prefetch_count == 0 {
728+ if self . prefetch_count ( ) == 0 {
731729 return ;
732730 }
733731
732+ match self . view_mode {
733+ ViewMode :: Single => self . prefetch_adjacent_single ( terminal_size) ,
734+ ViewMode :: Tile => self . prefetch_adjacent_tile ( terminal_size) ,
735+ }
736+ }
737+
738+ /// Prefetch next/previous images in Single mode (with wrap-around).
739+ fn prefetch_adjacent_single ( & mut self , terminal_size : Rect ) {
734740 let image_area = Self :: image_area ( terminal_size) ;
735741 let ( cell_w, cell_h) = self . picker . font_size ( ) ;
736742 if cell_w == 0 || cell_h == 0 || image_area. width == 0 || image_area. height == 0 {
@@ -741,25 +747,24 @@ impl App {
741747 let max_h_px = u32:: from ( image_area. height ) * u32:: from ( cell_h) ;
742748 let target = ( max_w_px, max_h_px) ;
743749
744- // Try to prefetch next and previous images
745750 let len = self . images . len ( ) ;
746751 if len <= 1 {
747752 return ;
748753 }
749754
750- // Build list of indices to prefetch: next N, then prev N
755+ // Build list of indices: next images first, then previous images
756+ let prefetch_count = self . prefetch_count ( ) ;
751757 let mut indices = Vec :: with_capacity ( prefetch_count * 2 ) ;
752758 for i in 1 ..=prefetch_count {
753- indices. push ( ( self . current_index + i) % len) ; // next
759+ indices. push ( ( self . current_index + i) % len) ;
754760 }
755761 for i in 1 ..=prefetch_count {
756- indices. push ( ( self . current_index + len - i) % len) ; // prev
762+ indices. push ( ( self . current_index + len - i) % len) ;
757763 }
758764
759765 for idx in indices {
760766 let path = & self . images [ idx] ;
761767
762- // Skip if already in cache
763768 let in_cache = self
764769 . render_cache
765770 . iter ( )
@@ -768,7 +773,6 @@ impl App {
768773 continue ;
769774 }
770775
771- // Send prefetch request
772776 self . worker . request ( ImageRequest {
773777 path : path. clone ( ) ,
774778 target,
@@ -783,7 +787,90 @@ impl App {
783787 tile_grid : None ,
784788 cell_size : None ,
785789 } ) ;
786- // Only prefetch one at a time to avoid overwhelming the worker
790+ break ;
791+ }
792+ }
793+
794+ /// Prefetch next/previous pages in Tile mode (no wrap-around).
795+ fn prefetch_adjacent_tile ( & mut self , terminal_size : Rect ) {
796+ let image_area = Self :: image_area ( terminal_size) ;
797+ let ( cell_w, cell_h) = self . picker . font_size ( ) ;
798+ if cell_w == 0 || cell_h == 0 || image_area. width == 0 || image_area. height == 0 {
799+ return ;
800+ }
801+
802+ let max_w_px = u32:: from ( image_area. width ) * u32:: from ( cell_w) ;
803+ let max_h_px = u32:: from ( image_area. height ) * u32:: from ( cell_h) ;
804+ let target = ( max_w_px, max_h_px) ;
805+
806+ let grid = Self :: calculate_tile_grid ( terminal_size, self . config . cell_aspect_ratio ) ;
807+ let ( cols, rows) = grid;
808+ let tiles_per_page = cols * rows;
809+ if tiles_per_page == 0 {
810+ return ;
811+ }
812+
813+ let len = self . images . len ( ) ;
814+ let total_pages = len. div_ceil ( tiles_per_page) ;
815+ if total_pages <= 1 {
816+ return ;
817+ }
818+
819+ let current_page = self . tile_cursor / tiles_per_page;
820+ let prefetch_count = self . prefetch_count ( ) ;
821+
822+ // Build list of page indices: next pages first, then previous pages
823+ let mut page_indices = Vec :: with_capacity ( prefetch_count * 2 ) ;
824+ for i in 1 ..=prefetch_count {
825+ let next_page = current_page + i;
826+ if next_page < total_pages {
827+ page_indices. push ( next_page) ;
828+ }
829+ }
830+ for i in 1 ..=prefetch_count {
831+ if current_page >= i {
832+ page_indices. push ( current_page - i) ;
833+ }
834+ }
835+
836+ for page in page_indices {
837+ let page_start = page * tiles_per_page;
838+ let cache_key = PathBuf :: from ( format ! ( "__tile_page_{}" , page_start) ) ;
839+
840+ let in_cache = self
841+ . render_cache
842+ . iter ( )
843+ . any ( |r| r. path == cache_key && r. target == target && r. fit_mode == self . fit_mode ) ;
844+ if in_cache {
845+ continue ;
846+ }
847+
848+ let tile_paths: Vec < PathBuf > = self
849+ . images
850+ . iter ( )
851+ . skip ( page_start)
852+ . take ( tiles_per_page)
853+ . cloned ( )
854+ . collect ( ) ;
855+
856+ if tile_paths. is_empty ( ) {
857+ continue ;
858+ }
859+
860+ self . worker . request ( ImageRequest {
861+ path : cache_key,
862+ target,
863+ fit_mode : self . fit_mode ,
864+ kgp_id : self . kgp_id ,
865+ is_tmux : self . is_tmux ,
866+ compress_level : self . config . compression_level ( ) ,
867+ tmux_kitty_max_pixels : self . config . tmux_kitty_max_pixels ,
868+ trace_worker : self . config . trace_worker ,
869+ view_mode : ViewMode :: Tile ,
870+ tile_paths : Some ( tile_paths) ,
871+ tile_grid : Some ( grid) ,
872+ cell_size : Some ( ( cell_w, cell_h) ) ,
873+ } ) ;
787874 break ;
788875 }
789876 }
0 commit comments