···71717272 // MARK: - Lookahead
73737474- /// Returns the next N photos from the current position across group boundaries
7474+ /// Returns the next N photos from the current position, wrapping around to start
7575 func photosAhead(_ count: Int) -> [Photo] {
7676+ let all = allPhotos
7777+ guard !all.isEmpty else { return [] }
7878+ guard let currentIndex = flatIndex else { return [] }
7679 var result: [Photo] = []
7777- var gi = selectedGroupIndex
7878- var pi = selectedPhotoIndex + 1
7979-8080- while result.count < count && gi < groups.count {
8181- let group = groups[gi]
8282- while pi < group.photos.count && result.count < count {
8383- result.append(group.photos[pi])
8484- pi += 1
8585- }
8686- gi += 1
8787- pi = 0
8080+ for i in 1...min(count, all.count - 1) {
8181+ result.append(all[(currentIndex + i) % all.count])
8882 }
8983 return result
9084 }
91859292- /// Returns the previous N photos from the current position across group boundaries
8686+ /// Returns the previous N photos from the current position, wrapping around to end
9387 func photosBehind(_ count: Int) -> [Photo] {
8888+ let all = allPhotos
8989+ guard !all.isEmpty else { return [] }
9090+ guard let currentIndex = flatIndex else { return [] }
9491 var result: [Photo] = []
9595- var gi = selectedGroupIndex
9696- var pi = selectedPhotoIndex - 1
9292+ for i in 1...min(count, all.count - 1) {
9393+ result.append(all[(currentIndex - i + all.count) % all.count])
9494+ }
9595+ return result
9696+ }
97979898- while result.count < count && gi >= 0 {
9999- let group = groups[gi]
100100- while pi >= 0 && result.count < count {
101101- result.append(group.photos[pi])
102102- pi -= 1
9898+ /// Current photo's index in the flat allPhotos array
9999+ private var flatIndex: Int? {
100100+ guard let photo = selectedPhoto else { return nil }
101101+ var idx = 0
102102+ for gi in 0..<groups.count {
103103+ for pi in 0..<groups[gi].photos.count {
104104+ if gi == selectedGroupIndex && pi == selectedPhotoIndex {
105105+ return idx
106106+ }
107107+ idx += 1
103108 }
104104- gi -= 1
105105- if gi >= 0 { pi = groups[gi].photos.count - 1 }
106109 }
107107- return result
110110+ return nil
108111 }
109112110113 // MARK: - Culling Actions
+4-2
cull/Views/ImportView.swift
···9595 }
9696 }
97979898- // Phase 3: Preload first 30 full-res previews (98-100%)
9999- let initialPreviews = Array(allPhotos.prefix(30))
9898+ // Phase 3: Preload initial full-res previews (98-100%)
9999+ let ahead = Array(allPhotos.prefix(30))
100100+ let behind = Array(allPhotos.suffix(30))
101101+ let initialPreviews = ahead + behind.reversed()
100102 var lastPreviewReported = 0.98
101103 await c.preloadAllPreviews(photos: initialPreviews) { p in
102104 let mapped = 0.98 + p * 0.02