Skip to main content

WIP don’t fetch the PHAsset immediately

ID
705bb3a
date
2023-06-15 07:32:45+00:00
author
Alex Chan <alex@alexwlchan.net>
parent
d7fb0ab
message
WIP don't fetch the PHAsset immediately
changed files
5 files, 61 additions, 36 deletions

Changed files

BlinkReviewer/Blink.xcodeproj/project.pbxproj (34154) → BlinkReviewer/Blink.xcodeproj/project.pbxproj (34154)

diff --git a/BlinkReviewer/Blink.xcodeproj/project.pbxproj b/BlinkReviewer/Blink.xcodeproj/project.pbxproj
index 2caaedb..9c9fb4d 100644
--- a/BlinkReviewer/Blink.xcodeproj/project.pbxproj
+++ b/BlinkReviewer/Blink.xcodeproj/project.pbxproj
@@ -588,7 +588,7 @@
 				CODE_SIGN_ENTITLEMENTS = Blink/Blink.entitlements;
 				CODE_SIGN_STYLE = Automatic;
 				COMBINE_HIDPI_IMAGES = YES;
-				CURRENT_PROJECT_VERSION = 10;
+				CURRENT_PROJECT_VERSION = 15;
 				DEVELOPMENT_ASSET_PATHS = "\"Blink/Preview Content\"";
 				ENABLE_PREVIEWS = YES;
 				GENERATE_INFOPLIST_FILE = YES;
@@ -615,7 +615,7 @@
 				CODE_SIGN_ENTITLEMENTS = Blink/Blink.entitlements;
 				CODE_SIGN_STYLE = Automatic;
 				COMBINE_HIDPI_IMAGES = YES;
-				CURRENT_PROJECT_VERSION = 10;
+				CURRENT_PROJECT_VERSION = 15;
 				DEVELOPMENT_ASSET_PATHS = "\"Blink/Preview Content\"";
 				ENABLE_PREVIEWS = YES;
 				GENERATE_INFOPLIST_FILE = YES;
@@ -640,7 +640,7 @@
 				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 10;
+				CURRENT_PROJECT_VERSION = 15;
 				GENERATE_INFOPLIST_FILE = YES;
 				MACOSX_DEPLOYMENT_TARGET = 13.3;
 				MARKETING_VERSION = 1.0;
@@ -658,7 +658,7 @@
 				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 10;
+				CURRENT_PROJECT_VERSION = 15;
 				GENERATE_INFOPLIST_FILE = YES;
 				MACOSX_DEPLOYMENT_TARGET = 13.3;
 				MARKETING_VERSION = 1.0;
@@ -675,7 +675,7 @@
 			buildSettings = {
 				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 10;
+				CURRENT_PROJECT_VERSION = 15;
 				GENERATE_INFOPLIST_FILE = YES;
 				MARKETING_VERSION = 1.0;
 				PRODUCT_BUNDLE_IDENTIFIER = net.alexwlchan.BlinkReviewerUITests;
@@ -691,7 +691,7 @@
 			buildSettings = {
 				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 10;
+				CURRENT_PROJECT_VERSION = 15;
 				GENERATE_INFOPLIST_FILE = YES;
 				MARKETING_VERSION = 1.0;
 				PRODUCT_BUNDLE_IDENTIFIER = net.alexwlchan.BlinkReviewerUITests;

BlinkReviewer/Blink/Photos/PhotosLibrary.swift (9492) → BlinkReviewer/Blink/Photos/PhotosLibrary.swift (9401)

diff --git a/BlinkReviewer/Blink/Photos/PhotosLibrary.swift b/BlinkReviewer/Blink/Photos/PhotosLibrary.swift
index d4e0fa9..10b0f9c 100644
--- a/BlinkReviewer/Blink/Photos/PhotosLibrary.swift
+++ b/BlinkReviewer/Blink/Photos/PhotosLibrary.swift
@@ -193,8 +193,7 @@ class PhotosLibrary: NSObject, ObservableObject, PHPhotoLibraryChangeObserver {
             let newImage = PHAssetImage(
                 asset,
                 size: CGSize(width: 70, height: 70),
-                deliveryMode: .opportunistic,
-                regenerateImmediately: false
+                deliveryMode: .opportunistic
             )
             
             thumbnailCache[asset] = newImage
@@ -218,8 +217,7 @@ class PhotosLibrary: NSObject, ObservableObject, PHPhotoLibraryChangeObserver {
             let newImage = PHAssetImage(
                 asset,
                 size: PHImageManagerMaximumSize,
-                deliveryMode: .opportunistic,
-                regenerateImmediately: true
+                deliveryMode: .opportunistic
             )
             
             fullSizeImageCache[asset] = newImage

BlinkReviewer/Blink/Views/Helpers/PHAssetHStack.swift (4975) → BlinkReviewer/Blink/Views/Helpers/PHAssetHStack.swift (4824)

diff --git a/BlinkReviewer/Blink/Views/Helpers/PHAssetHStack.swift b/BlinkReviewer/Blink/Views/Helpers/PHAssetHStack.swift
index 46a2762..031a147 100644
--- a/BlinkReviewer/Blink/Views/Helpers/PHAssetHStack.swift
+++ b/BlinkReviewer/Blink/Views/Helpers/PHAssetHStack.swift
@@ -37,18 +37,15 @@ struct AssetIdentifiersCollection: RandomAccessCollection, Equatable {
 /// items in the FetchResult, if necessary.
 ///
 struct PHAssetHStack<Content: View>: View {
-    var subview: (PHAsset, Int) -> Content
-    var fetchResult: PHFetchResult<PHAsset>
+    var subview: (String, Int) -> Content
     var assetIdentifiers: [String]
     
     init(
-        _ fetchResult: PHFetchResult<PHAsset>,
         assetIdentifiers: [String],
-        @ViewBuilder subview: @escaping (PHAsset, Int) -> Content
+        @ViewBuilder subview: @escaping (String, Int) -> Content
     ) {
         print("--> creating PHAssetHStack")
         self.subview = subview
-        self.fetchResult = fetchResult
         self.assetIdentifiers = assetIdentifiers
     }
     
@@ -76,7 +73,7 @@ struct PHAssetHStack<Content: View>: View {
                 //
                 // Note: enumerated is okay
                 ForEach(AssetIdentifiersCollection(assetIdentifiers: self.assetIdentifiers), id: \.1) { index, localIdentifier in
-                    subview(self.fetchResult.object(at: index), index)
+                    subview(localIdentifier, index)
                 }
                 
                 // Note: these two uses of RTL direction are a way to get the LazyHStack

BlinkReviewer/Blink/Views/Thumbnails/ThumbnailImage.swift (1601) → BlinkReviewer/Blink/Views/Thumbnails/ThumbnailImage.swift (2575)

diff --git a/BlinkReviewer/Blink/Views/Thumbnails/ThumbnailImage.swift b/BlinkReviewer/Blink/Views/Thumbnails/ThumbnailImage.swift
index e968d7e..29d51a9 100644
--- a/BlinkReviewer/Blink/Views/Thumbnails/ThumbnailImage.swift
+++ b/BlinkReviewer/Blink/Views/Thumbnails/ThumbnailImage.swift
@@ -1,6 +1,19 @@
 import SwiftUI
 import Photos
 
+struct ThumbnailImageInner: View {
+    @ObservedObject var assetImage: PHAssetImage
+    var size: CGFloat
+    
+    var body: some View {
+        Image(nsImage: assetImage.image)
+            .resizable()
+            .scaledToFill()
+            .clipped()
+            .frame(width: size, height: size, alignment: .center)
+    }
+}
+
 /// Render a single thumbnail image in the thumbnail picker.
 ///
 /// Thumbnails are square, and they expand to fill the square.  This may
@@ -8,6 +21,8 @@ import Photos
 /// small previews, not complete images.
 struct ThumbnailImage: View {
     
+    @EnvironmentObject var photosLibrary: PhotosLibrary
+    
     // Implementation note: the reason we pass in a bunch of individual
     // properties rather than the whole asset is because we need an
     // @EnvironmentObject (the PhotosLibrary) to create the PHAssetImage,
@@ -16,10 +31,18 @@ struct ThumbnailImage: View {
     // But EnvironmentObject values aren't passed down until you call the
     // `body` method, which is too late!  So instead we have the parent
     // view call into PhotosLibrary and pass in the relevant values here.
-    @ObservedObject var assetImage: PHAssetImage
-    var state: ReviewState?
+    @State var assetImage: PHAssetImage? = nil
+    
+    var index: Int
+    @State var state: ReviewState? = nil
     var isFocused: Bool
-    var isFavorite: Bool
+    @State var isFavorite: Bool = false
+    
+    init(index: Int, isFocused: Bool) {
+        print("creating thumbnail image")
+        self.index = index
+        self.isFocused = isFocused
+    }
     
     private func size() -> CGFloat {
         isFocused ? 70 : 50
@@ -30,15 +53,25 @@ struct ThumbnailImage: View {
     }
     
     var body: some View {
-        Image(nsImage: assetImage.image)
-            .resizable()
-            .scaledToFill()
-            .clipped()
-            .frame(width: size(), height: size(), alignment: .center)
-            .cornerRadius(cornerRadius())
-            .reviewStateColor(isRejected: state == .Rejected)
-            .reviewStateBorder(for: state, with: cornerRadius())
-            .reviewStateIcon(for: state, isFocused)
-            .favoriteHeartIcon(isFavorite, isFocused)
+        if let thisAssetImage = assetImage {
+            ThumbnailImageInner(assetImage: thisAssetImage, size: size())
+                .cornerRadius(cornerRadius())
+                .reviewStateColor(isRejected: state == .Rejected)
+                .reviewStateBorder(for: state, with: cornerRadius())
+                .reviewStateIcon(for: state, isFocused)
+                .favoriteHeartIcon(isFavorite, isFocused)
+                
+        } else {
+            ProgressView()
+                .onAppear {
+                    let asset = photosLibrary.asset(at: index)
+                    
+                    self.state = photosLibrary.state(of: asset)
+                    self.isFavorite = asset.isFavorite
+                    
+                    self.assetImage = photosLibrary.getThumbnail(for: asset)
+                }
+        }
+        
     }
 }

BlinkReviewer/Blink/Views/Thumbnails/ThumbnailList.swift (1125) → BlinkReviewer/Blink/Views/Thumbnails/ThumbnailList.swift (975)

diff --git a/BlinkReviewer/Blink/Views/Thumbnails/ThumbnailList.swift b/BlinkReviewer/Blink/Views/Thumbnails/ThumbnailList.swift
index a8ba73e..c90f6e7 100644
--- a/BlinkReviewer/Blink/Views/Thumbnails/ThumbnailList.swift
+++ b/BlinkReviewer/Blink/Views/Thumbnails/ThumbnailList.swift
@@ -13,13 +13,10 @@ struct ThumbnailList: View {
     
     var body: some View {
         ScrollViewReader { proxy in
-            PHAssetHStack(photosLibrary.assets, assetIdentifiers: photosLibrary.assetIdentifiers) { asset, index in
-                ThumbnailImage(
-                    assetImage: photosLibrary.getThumbnail(for: asset),
-                    state: photosLibrary.state(of: asset),
-                    isFocused: index == focusedAssetIndex,
-                    isFavorite: asset.isFavorite
-                ).onTapGesture {
+            PHAssetHStack(assetIdentifiers: photosLibrary.assetIdentifiers) { localIdentifier, index in
+                ThumbnailImage(index: index, isFocused: index == focusedAssetIndex)
+                .environmentObject(photosLibrary)
+                .onTapGesture {
                     focusedAssetIndex = index
                 }
             }