Add some more comments, move things around
- ID
fc9e76c- date
2023-06-16 06:41:41+00:00- author
Alex Chan <alex@alexwlchan.net>- parent
1feb066- message
Add some more comments, move things around- changed files
2 files, 82 additions, 62 deletions
Changed files
BlinkReviewer/Blink.xcodeproj/project.pbxproj (34735) → BlinkReviewer/Blink.xcodeproj/project.pbxproj (34735)
diff --git a/BlinkReviewer/Blink.xcodeproj/project.pbxproj b/BlinkReviewer/Blink.xcodeproj/project.pbxproj
index d4af973..3c053f4 100644
--- a/BlinkReviewer/Blink.xcodeproj/project.pbxproj
+++ b/BlinkReviewer/Blink.xcodeproj/project.pbxproj
@@ -600,7 +600,7 @@
CODE_SIGN_ENTITLEMENTS = Blink/Blink.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 48;
+ CURRENT_PROJECT_VERSION = 51;
DEVELOPMENT_ASSET_PATHS = "\"Blink/Preview Content\"";
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
@@ -627,7 +627,7 @@
CODE_SIGN_ENTITLEMENTS = Blink/Blink.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 48;
+ CURRENT_PROJECT_VERSION = 51;
DEVELOPMENT_ASSET_PATHS = "\"Blink/Preview Content\"";
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
@@ -652,7 +652,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 48;
+ CURRENT_PROJECT_VERSION = 51;
GENERATE_INFOPLIST_FILE = YES;
MACOSX_DEPLOYMENT_TARGET = 13.3;
MARKETING_VERSION = 1.0;
@@ -670,7 +670,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 48;
+ CURRENT_PROJECT_VERSION = 51;
GENERATE_INFOPLIST_FILE = YES;
MACOSX_DEPLOYMENT_TARGET = 13.3;
MARKETING_VERSION = 1.0;
@@ -687,7 +687,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 48;
+ CURRENT_PROJECT_VERSION = 51;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = net.alexwlchan.BlinkReviewerUITests;
@@ -703,7 +703,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 48;
+ CURRENT_PROJECT_VERSION = 51;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = net.alexwlchan.BlinkReviewerUITests;
BlinkReviewer/Blink/Photos/PhotosLibrary.swift (15968) → BlinkReviewer/Blink/Photos/PhotosLibrary.swift (16753)
diff --git a/BlinkReviewer/Blink/Photos/PhotosLibrary.swift b/BlinkReviewer/Blink/Photos/PhotosLibrary.swift
index 5dd9502..9eda73d 100644
--- a/BlinkReviewer/Blink/Photos/PhotosLibrary.swift
+++ b/BlinkReviewer/Blink/Photos/PhotosLibrary.swift
@@ -119,7 +119,17 @@ class PhotosLibrary: NSObject, ObservableObject, PHPhotoLibraryChangeObserver {
// ahead and populate all the initial data structures.
if !self.isPhotoLibraryAuthorized && PHPhotoLibrary.authorizationStatus() == .authorized {
getInitialData()
- self.isPhotoLibraryAuthorized = PHPhotoLibrary.authorizationStatus() == .authorized
+
+ // This is wrapped in an async dispatch to fix a warning from Xcode:
+ //
+ // Publishing changes from background threads is not allowed; make sure
+ // to publish values from the main thread (via operators like receive(on:))
+ // on model updates.
+ //
+ DispatchQueue.main.async {
+ self.isPhotoLibraryAuthorized = PHPhotoLibrary.authorizationStatus() == .authorized
+ }
+
return
}
@@ -186,6 +196,10 @@ class PhotosLibrary: NSObject, ObservableObject, PHPhotoLibraryChangeObserver {
}
}
+ /// Retrieve an asset at a particular position.
+ ///
+ /// Just a convenience wrapper around PHFetchResult.object(at: Int).
+ ///
func asset(at index: Int) -> PHAsset {
assets.object(at: index)
}
@@ -240,6 +254,67 @@ class PhotosLibrary: NSObject, ObservableObject, PHPhotoLibraryChangeObserver {
return nil
}
+ /// Set the review state of an asset.
+ ///
+ /// This will record the change in the Photos Library and update any internal
+ /// data structures.
+ ///
+ func setState(ofAsset asset: PHAsset, to newState: ReviewState) -> Void {
+ let existingState = self.state(of: asset)
+
+ try! PHPhotoLibrary.shared().performChangesAndWait {
+ // The first condition is a combination of two:
+ //
+ // -- the photo is already approved and you hit the "approve" hotkey,
+ // -- so un-approve it
+ // state == .Approved && e.characters == "1"
+ //
+ // -- the photo is already approved and you selected a different review
+ // -- state, so unapprove it
+ // state == .Approved && e.characters != "1"
+ //
+ // We can optimise it into a single case, but it does make sense!
+ //
+ // Similar logic applies for all three conditions.
+ if existingState == .Approved {
+ asset.remove(fromAlbum: self.approved)
+ } else if newState == .Approved {
+ asset.add(toAlbum: self.approved)
+ }
+
+ if existingState == .Rejected {
+ asset.remove(fromAlbum: self.rejected)
+ } else if newState == .Rejected {
+ asset.add(toAlbum: self.rejected)
+ }
+
+ if existingState == .NeedsAction {
+ asset.remove(fromAlbum: self.needsAction)
+ } else if newState == .NeedsAction {
+ asset.add(toAlbum: self.needsAction)
+ }
+ }
+
+ if existingState == .Approved {
+ self.approvedAssetIdentifiers.remove(asset.localIdentifier)
+ } else if newState == .Approved {
+ self.approvedAssetIdentifiers.insert(asset.localIdentifier)
+ }
+
+ if existingState == .Rejected {
+ self.rejectedAssetIdentifiers.remove(asset.localIdentifier)
+ } else if newState == .Rejected {
+ self.rejectedAssetIdentifiers.insert(asset.localIdentifier)
+ }
+
+ if existingState == .NeedsAction {
+ self.needsActionAssetIdentifiers.remove(asset.localIdentifier)
+ } else if newState == .NeedsAction {
+ self.needsActionAssetIdentifiers.insert(asset.localIdentifier)
+ }
+ }
+
+ /// Returns true if this asset is a favorite, false otherwise.
func isFavorite(localIdentifier: String) -> Bool {
self.favoriteAssetIdentifiers.contains(localIdentifier)
}
@@ -319,61 +394,6 @@ class PhotosLibrary: NSObject, ObservableObject, PHPhotoLibraryChangeObserver {
self.assetIdentifiers = assetIdentifiers
self.favoriteAssetIdentifiers = favoriteAssetIdentifiers
}
-
- func setState(ofAsset asset: PHAsset, to newState: ReviewState) -> Void {
- let existingState = self.state(of: asset)
-
- try! PHPhotoLibrary.shared().performChangesAndWait {
- // The first condition is a combination of two:
- //
- // -- the photo is already approved and you hit the "approve" hotkey,
- // -- so un-approve it
- // state == .Approved && e.characters == "1"
- //
- // -- the photo is already approved and you selected a different review
- // -- state, so unapprove it
- // state == .Approved && e.characters != "1"
- //
- // We can optimise it into a single case, but it does make sense!
- //
- // Similar logic applies for all three conditions.
- if existingState == .Approved {
- asset.remove(fromAlbum: self.approved)
- } else if newState == .Approved {
- asset.add(toAlbum: self.approved)
- }
-
- if existingState == .Rejected {
- asset.remove(fromAlbum: self.rejected)
- } else if newState == .Rejected {
- asset.add(toAlbum: self.rejected)
- }
-
- if existingState == .NeedsAction {
- asset.remove(fromAlbum: self.needsAction)
- } else if newState == .NeedsAction {
- asset.add(toAlbum: self.needsAction)
- }
- }
-
- if existingState == .Approved {
- self.approvedAssetIdentifiers.remove(asset.localIdentifier)
- } else if newState == .Approved {
- self.approvedAssetIdentifiers.insert(asset.localIdentifier)
- }
-
- if existingState == .Rejected {
- self.rejectedAssetIdentifiers.remove(asset.localIdentifier)
- } else if newState == .Rejected {
- self.rejectedAssetIdentifiers.insert(asset.localIdentifier)
- }
-
- if existingState == .NeedsAction {
- self.needsActionAssetIdentifiers.remove(asset.localIdentifier)
- } else if newState == .NeedsAction {
- self.needsActionAssetIdentifiers.insert(asset.localIdentifier)
- }
- }
}
func getSetOfIdentifiers(fetchResult: PHFetchResult<PHAsset>) -> Set<String> {