Skip to main content

Add coloured icons to show what review state a photo is in

ID
32918c6
date
2023-06-08 14:29:55+00:00
author
Alex Chan <alex@alexwlchan.net>
parent
ae1b773
message
Add coloured icons to show what review state a photo is in
changed files
6 files, 132 additions, 48 deletions

Changed files

BlinkReviewer/BlinkReviewer/Model/ReviewState.swift (0) → BlinkReviewer/BlinkReviewer/Model/ReviewState.swift (822)

diff --git a/BlinkReviewer/BlinkReviewer/Model/ReviewState.swift b/BlinkReviewer/BlinkReviewer/Model/ReviewState.swift
new file mode 100644
index 0000000..0806639
--- /dev/null
+++ b/BlinkReviewer/BlinkReviewer/Model/ReviewState.swift
@@ -0,0 +1,40 @@
+//
+//  ReviewState.swift
+//  BlinkReviewer
+//
+//  Created by Alex Chan on 08/06/2023.
+//
+
+import Foundation
+import SwiftUI
+
+enum ReviewState {
+    case Approved
+    case Rejected
+    case NeedsAction
+    
+    func color() -> Color {
+        switch(self) {
+            case .Approved:
+                return .green
+            
+            case .Rejected:
+                return .red
+            
+            case .NeedsAction:
+                return .blue
+        }
+    }
+    
+    func icon() -> Image {
+        switch(self) {
+            case .Approved:
+                return Image(systemName: "checkmark.circle.fill")
+            case .Rejected:
+                return Image(systemName: "trash.circle.fill")
+            case .NeedsAction:
+                return Image(systemName: "info.circle.fill")
+        }
+    }
+}
+

BlinkReviewer/BlinkReviewer/Photos/AssetHelpers.swift (2426) → BlinkReviewer/BlinkReviewer/Photos/AssetHelpers.swift (2934)

diff --git a/BlinkReviewer/BlinkReviewer/Photos/AssetHelpers.swift b/BlinkReviewer/BlinkReviewer/Photos/AssetHelpers.swift
index 80ba71a..97722b5 100644
--- a/BlinkReviewer/BlinkReviewer/Photos/AssetHelpers.swift
+++ b/BlinkReviewer/BlinkReviewer/Photos/AssetHelpers.swift
@@ -35,6 +35,25 @@ extension PHAsset {
         return result
     }
     
+    func state() -> ReviewState? {
+        var result: ReviewState? = nil
+        
+        self.albums().forEach { album in
+            switch (album.localizedTitle) {
+                case "Approved":
+                    result = .Approved
+                case "Rejected":
+                    result = .Rejected
+                case "Needs Action":
+                    result = .NeedsAction
+                default:
+                    break
+            }
+        }
+        
+        return result
+    }
+    
     private func getImageForSize(size: CGSize) -> NSImage {
         // This implementation is based on code in a Stack Overflow answer
         // by Francois Nadeau: https://stackoverflow.com/a/48755517/1558022

BlinkReviewer/BlinkReviewer/Views/AlbumInfo.swift (1023) → BlinkReviewer/BlinkReviewer/Views/AlbumInfo.swift (1068)

diff --git a/BlinkReviewer/BlinkReviewer/Views/AlbumInfo.swift b/BlinkReviewer/BlinkReviewer/Views/AlbumInfo.swift
index 31b06d3..1e4a1be 100644
--- a/BlinkReviewer/BlinkReviewer/Views/AlbumInfo.swift
+++ b/BlinkReviewer/BlinkReviewer/Views/AlbumInfo.swift
@@ -29,6 +29,7 @@ struct AlbumInfo: View {
                         .padding(5)
                         .background(.white.opacity(0.9))
                         .cornerRadius(7.0)
+                        .shadow(radius: 2.0)
                 }
             }
         }.padding()

BlinkReviewer/BlinkReviewer/Views/SwiftUIView.swift (0) → BlinkReviewer/BlinkReviewer/Views/SwiftUIView.swift (354)

diff --git a/BlinkReviewer/BlinkReviewer/Views/SwiftUIView.swift b/BlinkReviewer/BlinkReviewer/Views/SwiftUIView.swift
new file mode 100644
index 0000000..c6aa691
--- /dev/null
+++ b/BlinkReviewer/BlinkReviewer/Views/SwiftUIView.swift
@@ -0,0 +1,20 @@
+//
+//  SwiftUIView.swift
+//  BlinkReviewer
+//
+//  Created by Alex Chan on 08/06/2023.
+//
+
+import SwiftUI
+
+struct SwiftUIView: View {
+    var body: some View {
+        Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
+    }
+}
+
+struct SwiftUIView_Previews: PreviewProvider {
+    static var previews: some View {
+        SwiftUIView()
+    }
+}

BlinkReviewer/BlinkReviewer/Views/ThumbnailImage.swift (3039) → BlinkReviewer/BlinkReviewer/Views/ThumbnailImage.swift (3314)

diff --git a/BlinkReviewer/BlinkReviewer/Views/ThumbnailImage.swift b/BlinkReviewer/BlinkReviewer/Views/ThumbnailImage.swift
index 64dfb7e..d812e45 100644
--- a/BlinkReviewer/BlinkReviewer/Views/ThumbnailImage.swift
+++ b/BlinkReviewer/BlinkReviewer/Views/ThumbnailImage.swift
@@ -8,62 +8,26 @@
 import SwiftUI
 import Photos
 
-enum ReviewState {
-    case Approved
-    case Rejected
-    case NeedsAction
-}
-
 /// Renders a square thumbnail for an image.
 ///
 /// The image will be expanded to fill the square, and may be clipped
 /// if the original aspect ratio isn't square.
 struct ThumbnailImage: View {
-    var asset: PHAsset
+    var thumbnail: NSImage
+    var state: ReviewState?
+    var isFavorite: Bool
     var isSelected: Bool
     
     var size: CGFloat {
         isSelected ? 70.0 : 50.0
     }
     
-    var state: ReviewState? {
-        var result: ReviewState? = nil
-        
-        asset.albums().forEach { album in
-            switch (album.localizedTitle) {
-                case "Approved":
-                    result = .Approved
-                case "Rejected":
-                    result = .Rejected
-                case "Needs Action":
-                    result = .NeedsAction
-                default:
-                    break
-            }
-        }
-        
-        return result
-    }
-    
-    var stateColor: Color {
-        switch (state) {
-            case .Approved:
-                return .green
-            case .Rejected:
-                return .red
-            case .NeedsAction:
-                return .blue
-            default:
-                return .gray.opacity(0.5)
-        }
-    }
-    
     var cornerRadius: CGFloat {
         return isSelected ? 7.0 : 5.0
     }
     
     var body: some View {
-        Image(nsImage: asset.getThumbnail())
+        Image(nsImage: thumbnail)
             .resizable()
             // Note: it's taken several attempts to get this working correctly;
             // it behaves differently in the running app to the SwiftUI preview.
@@ -77,14 +41,17 @@ struct ThumbnailImage: View {
             .scaledToFill()
             .frame(width: size, height: size, alignment: .center)
             .clipped()
-            .cornerRadius(cornerRadius)
             .overlay(
                 // https://www.appcoda.com/swiftui-border/
                 RoundedRectangle(cornerRadius: cornerRadius)
-                    .stroke(stateColor, lineWidth: state != nil ? 3.0 : 1.0)
+                    .stroke(
+                        state?.color() ?? .gray.opacity(0.7),
+                        lineWidth: state != nil ? 3.0 : 1.0
+                    )
             )
+            .cornerRadius(cornerRadius)
             .overlay(alignment: Alignment(horizontal: .leading, vertical: .bottom)) {
-                if (asset.isFavorite) {
+                if (isFavorite) {
                     Image(systemName: "heart.fill")
                         .foregroundColor(.white)
                         .padding(2)
@@ -92,11 +59,46 @@ struct ThumbnailImage: View {
                 }
             }
             .overlay(alignment: Alignment(horizontal: .leading, vertical: .top)) {
-                if (state != nil) {
-                    Image(systemName: "checkmark.circle.fill").foregroundColor(stateColor).accentColor(.white).padding(2).font(.title2)
-//                    "info.circle.fill"
-//                    "trash.circle.fill
+                if let thisState = state {
+                    thisState.icon()
+                        .foregroundStyle(.white, thisState.color())
+                        .symbolRenderingMode(.palette)
+                        .padding(2)
+                        .font(.title2)
+                        .shadow(radius: 2.0)
                 }
             }
     }
 }
+
+struct ThumbnailImage_Previews: PreviewProvider {
+    static var previews: some View {
+        ThumbnailImage(
+            thumbnail: NSImage(named: "IMG_5934")!,
+            state: .Approved,
+            isFavorite: true,
+            isSelected: true
+        ).previewDisplayName("approved, favorite")
+        
+        ThumbnailImage(
+            thumbnail: NSImage(named: "IMG_5934")!,
+            state: .Rejected,
+            isFavorite: false,
+            isSelected: false
+        ).previewDisplayName("rejected")
+        
+        ThumbnailImage(
+            thumbnail: NSImage(named: "IMG_5934")!,
+            state: .NeedsAction,
+            isFavorite: false,
+            isSelected: false
+        ).previewDisplayName("needs action")
+        
+        ThumbnailImage(
+            thumbnail: NSImage(named: "IMG_5934")!,
+            state: nil,
+            isFavorite: false,
+            isSelected: false
+        ).previewDisplayName("no state")
+    }
+}

BlinkReviewer/BlinkReviewer/Views/ThumbnailList.swift (2810) → BlinkReviewer/BlinkReviewer/Views/ThumbnailList.swift (2937)

diff --git a/BlinkReviewer/BlinkReviewer/Views/ThumbnailList.swift b/BlinkReviewer/BlinkReviewer/Views/ThumbnailList.swift
index cec0cdb..6bacfef 100644
--- a/BlinkReviewer/BlinkReviewer/Views/ThumbnailList.swift
+++ b/BlinkReviewer/BlinkReviewer/Views/ThumbnailList.swift
@@ -32,7 +32,9 @@ struct ThumbnailList: View {
                     // the thumbnails every time you change position.
                     ForEach(Array(displayAssets().enumerated()), id: \.element.localIdentifier) { index, asset in
                         ThumbnailImage(
-                            asset: asset,
+                            thumbnail: asset.getThumbnail(),
+                            state: asset.state(),
+                            isFavorite: asset.isFavorite,
                             isSelected: displayAssets()[displaySelectedAssetIndex()].localIdentifier == asset.localIdentifier
                         ).onTapGesture {
                             selectedAssetIndex = assets.count - 1 - index