its whats on the tin; culls raw photos
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: wrap loading

+30 -25
+26 -23
cull/Models/CullSession.swift
··· 71 71 72 72 // MARK: - Lookahead 73 73 74 - /// Returns the next N photos from the current position across group boundaries 74 + /// Returns the next N photos from the current position, wrapping around to start 75 75 func photosAhead(_ count: Int) -> [Photo] { 76 + let all = allPhotos 77 + guard !all.isEmpty else { return [] } 78 + guard let currentIndex = flatIndex else { return [] } 76 79 var result: [Photo] = [] 77 - var gi = selectedGroupIndex 78 - var pi = selectedPhotoIndex + 1 79 - 80 - while result.count < count && gi < groups.count { 81 - let group = groups[gi] 82 - while pi < group.photos.count && result.count < count { 83 - result.append(group.photos[pi]) 84 - pi += 1 85 - } 86 - gi += 1 87 - pi = 0 80 + for i in 1...min(count, all.count - 1) { 81 + result.append(all[(currentIndex + i) % all.count]) 88 82 } 89 83 return result 90 84 } 91 85 92 - /// Returns the previous N photos from the current position across group boundaries 86 + /// Returns the previous N photos from the current position, wrapping around to end 93 87 func photosBehind(_ count: Int) -> [Photo] { 88 + let all = allPhotos 89 + guard !all.isEmpty else { return [] } 90 + guard let currentIndex = flatIndex else { return [] } 94 91 var result: [Photo] = [] 95 - var gi = selectedGroupIndex 96 - var pi = selectedPhotoIndex - 1 92 + for i in 1...min(count, all.count - 1) { 93 + result.append(all[(currentIndex - i + all.count) % all.count]) 94 + } 95 + return result 96 + } 97 97 98 - while result.count < count && gi >= 0 { 99 - let group = groups[gi] 100 - while pi >= 0 && result.count < count { 101 - result.append(group.photos[pi]) 102 - pi -= 1 98 + /// Current photo's index in the flat allPhotos array 99 + private var flatIndex: Int? { 100 + guard let photo = selectedPhoto else { return nil } 101 + var idx = 0 102 + for gi in 0..<groups.count { 103 + for pi in 0..<groups[gi].photos.count { 104 + if gi == selectedGroupIndex && pi == selectedPhotoIndex { 105 + return idx 106 + } 107 + idx += 1 103 108 } 104 - gi -= 1 105 - if gi >= 0 { pi = groups[gi].photos.count - 1 } 106 109 } 107 - return result 110 + return nil 108 111 } 109 112 110 113 // MARK: - Culling Actions
+4 -2
cull/Views/ImportView.swift
··· 95 95 } 96 96 } 97 97 98 - // Phase 3: Preload first 30 full-res previews (98-100%) 99 - let initialPreviews = Array(allPhotos.prefix(30)) 98 + // Phase 3: Preload initial full-res previews (98-100%) 99 + let ahead = Array(allPhotos.prefix(30)) 100 + let behind = Array(allPhotos.suffix(30)) 101 + let initialPreviews = ahead + behind.reversed() 100 102 var lastPreviewReported = 0.98 101 103 await c.preloadAllPreviews(photos: initialPreviews) { p in 102 104 let mapped = 0.98 + p * 0.02