Skip to main content

Don’t show the progress indicator for the first second

ID
7547102
date
2023-06-09 14:24:49+00:00
author
Alex Chan <alex@alexwlchan.net>
parent
b934093
message
Don't show the progress indicator for the first second
changed files
3 files, 41 additions, 12 deletions

Changed files

BlinkReviewer/BlinkReviewer.xcodeproj/project.pbxproj (27079) → BlinkReviewer/BlinkReviewer.xcodeproj/project.pbxproj (27732)

diff --git a/BlinkReviewer/BlinkReviewer.xcodeproj/project.pbxproj b/BlinkReviewer/BlinkReviewer.xcodeproj/project.pbxproj
index 7f1c8fb..85b8459 100644
--- a/BlinkReviewer/BlinkReviewer.xcodeproj/project.pbxproj
+++ b/BlinkReviewer/BlinkReviewer.xcodeproj/project.pbxproj
@@ -7,6 +7,7 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		940331732A336B5100200C5D /* DeferredRendering.swift in Sources */ = {isa = PBXBuildFile; fileRef = 940331722A336B5100200C5D /* DeferredRendering.swift */; };
 		94D2C8B92A320E6F00BEE15B /* ReviewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D2C8B82A320E6F00BEE15B /* ReviewState.swift */; };
 		94D2C8BD2A32796500BEE15B /* AlbumHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D2C8BC2A32796500BEE15B /* AlbumHelpers.swift */; };
 		94D2C8BF2A3299BD00BEE15B /* PhotosLibrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D2C8BE2A3299BD00BEE15B /* PhotosLibrary.swift */; };
@@ -44,6 +45,7 @@
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXFileReference section */
+		940331722A336B5100200C5D /* DeferredRendering.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeferredRendering.swift; sourceTree = "<group>"; };
 		94D2C8B82A320E6F00BEE15B /* ReviewState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReviewState.swift; sourceTree = "<group>"; };
 		94D2C8BC2A32796500BEE15B /* AlbumHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumHelpers.swift; sourceTree = "<group>"; };
 		94D2C8BE2A3299BD00BEE15B /* PhotosLibrary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotosLibrary.swift; sourceTree = "<group>"; };
@@ -92,6 +94,14 @@
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
+		940331742A336BEB00200C5D /* Helpers */ = {
+			isa = PBXGroup;
+			children = (
+				940331722A336B5100200C5D /* DeferredRendering.swift */,
+			);
+			path = Helpers;
+			sourceTree = "<group>";
+		};
 		94D2C8B72A320E6600BEE15B /* Model */ = {
 			isa = PBXGroup;
 			children = (
@@ -162,6 +172,7 @@
 		94D7511A2A31A7A6005859E7 /* Views */ = {
 			isa = PBXGroup;
 			children = (
+				940331742A336BEB00200C5D /* Helpers */,
 				94D7511B2A31A7B1005859E7 /* ThumbnailImage.swift */,
 				94D7511D2A31B243005859E7 /* FullSizeImage.swift */,
 				94D7511F2A31B53E005859E7 /* AlbumInfo.swift */,
@@ -319,6 +330,7 @@
 				94D2C8BF2A3299BD00BEE15B /* PhotosLibrary.swift in Sources */,
 				94D7511E2A31B243005859E7 /* FullSizeImage.swift in Sources */,
 				94D750F02A31A796005859E7 /* BlinkReviewerApp.swift in Sources */,
+				940331732A336B5100200C5D /* DeferredRendering.swift in Sources */,
 				94D751202A31B53E005859E7 /* AlbumInfo.swift in Sources */,
 				94D751302A31DC4A005859E7 /* ThumbnailList.swift in Sources */,
 				94D751222A31BD8E005859E7 /* PhotoReviewer.swift in Sources */,

BlinkReviewer/BlinkReviewer/Views/FullSizeImage.swift (1864) → BlinkReviewer/BlinkReviewer/Views/FullSizeImage.swift (2660)

diff --git a/BlinkReviewer/BlinkReviewer/Views/FullSizeImage.swift b/BlinkReviewer/BlinkReviewer/Views/FullSizeImage.swift
index 33dbfa0..2570993 100644
--- a/BlinkReviewer/BlinkReviewer/Views/FullSizeImage.swift
+++ b/BlinkReviewer/BlinkReviewer/Views/FullSizeImage.swift
@@ -38,6 +38,16 @@ struct FullSizeImage: View {
                                     .colorInvert()
                                     .brightness(1)
                                     .padding()
+                                    .deferredRendering(
+                                        // Note: even if the image is already cached locally, the
+                                        // image caching manager typically sends two images: a low-res
+                                        // version comes immediately, then a higher-res version within
+                                        // a second or two.  This causes the progress indicator to
+                                        // "flash" -- it appears then almost instantly disappears.
+                                        //
+                                        // Deferring the rendering by a second avoids this "flash".
+                                        for: .seconds(1)
+                                    )
                             }
                             
                         }

BlinkReviewer/BlinkReviewer/Views/Helpers/DeferredRendering.swift (919) → BlinkReviewer/BlinkReviewer/Views/Helpers/DeferredRendering.swift (1176)

diff --git a/BlinkReviewer/BlinkReviewer/Views/Helpers/DeferredRendering.swift b/BlinkReviewer/BlinkReviewer/Views/Helpers/DeferredRendering.swift
index bb12641..16bf922 100644
--- a/BlinkReviewer/BlinkReviewer/Views/Helpers/DeferredRendering.swift
+++ b/BlinkReviewer/BlinkReviewer/Views/Helpers/DeferredRendering.swift
@@ -1,21 +1,28 @@
-//
-//  DeferredRendering.swift
-//  BlinkReviewer
-//
-//  Created by Alex Chan on 09/06/2023.
-//
-
 import SwiftUI
 
-/// A ViewModifier that defers its rendering until after the provided threshold surpasses
+/// Defers the rendering of a view for the given period.
+///
+/// For example:
+///
+/// ```swift
+/// Text("Hello, world!")
+///     .deferredRendering(for: .seconds(5))
+/// ```
+///
+/// will not display the text "Hello, world!" until five seconds after the
+/// view is initially rendered.
+///
+/// This is based on code xwritten by Yonat and Charlton Provatas on
+/// Stack Overflow, see https://stackoverflow.com/a/74765430/1558022
+///
 private struct DeferredViewModifier: ViewModifier {
 
-    let threshold: Double
+    let delay: DispatchTimeInterval
 
     func body(content: Content) -> some View {
         _content(content)
             .onAppear {
-               DispatchQueue.main.asyncAfter(deadline: .now() + threshold) {
+               DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
                    self.shouldRender = true
                }
             }
@@ -34,7 +41,7 @@ private struct DeferredViewModifier: ViewModifier {
 }
 
 extension View {
-    func deferredRendering(for seconds: Double) -> some View {
-        modifier(DeferredViewModifier(threshold: seconds))
+    func deferredRendering(for delay: DispatchTimeInterval) -> some View {
+        modifier(DeferredViewModifier(delay: delay))
     }
 }