diff --git a/Vernissage.xcodeproj/project.pbxproj b/Vernissage.xcodeproj/project.pbxproj index f68a799..062a170 100644 --- a/Vernissage.xcodeproj/project.pbxproj +++ b/Vernissage.xcodeproj/project.pbxproj @@ -1206,7 +1206,7 @@ CODE_SIGN_ENTITLEMENTS = VernissageWidget/VernissageWidgetExtension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 128; + CURRENT_PROJECT_VERSION = 129; DEVELOPMENT_TEAM = B2U9FEKYP8; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = VernissageWidget/Info.plist; @@ -1234,7 +1234,7 @@ ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; CODE_SIGN_ENTITLEMENTS = VernissageWidget/VernissageWidgetExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 128; + CURRENT_PROJECT_VERSION = 129; DEVELOPMENT_TEAM = B2U9FEKYP8; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = VernissageWidget/Info.plist; @@ -1261,7 +1261,7 @@ CODE_SIGN_ENTITLEMENTS = VernissageShare/VernissageShareExtension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 128; + CURRENT_PROJECT_VERSION = 129; DEVELOPMENT_TEAM = B2U9FEKYP8; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = VernissageShare/Info.plist; @@ -1288,7 +1288,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = VernissageShare/VernissageShareExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 128; + CURRENT_PROJECT_VERSION = 129; DEVELOPMENT_TEAM = B2U9FEKYP8; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = VernissageShare/Info.plist; @@ -1437,7 +1437,7 @@ CODE_SIGN_ENTITLEMENTS = Vernissage/Vernissage.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 128; + CURRENT_PROJECT_VERSION = 129; DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\""; DEVELOPMENT_TEAM = B2U9FEKYP8; ENABLE_PREVIEWS = YES; @@ -1479,7 +1479,7 @@ ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; CODE_SIGN_ENTITLEMENTS = Vernissage/Vernissage.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 128; + CURRENT_PROJECT_VERSION = 129; DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\""; DEVELOPMENT_TEAM = B2U9FEKYP8; ENABLE_PREVIEWS = YES; diff --git a/Vernissage/Widgets/ImageRowItem.swift b/Vernissage/Widgets/ImageRowItem.swift index 0b00df2..c493508 100644 --- a/Vernissage/Widgets/ImageRowItem.swift +++ b/Vernissage/Widgets/ImageRowItem.swift @@ -5,6 +5,7 @@ // import SwiftUI +import Nuke import ClientKit import ServicesKit import EnvironmentKit @@ -17,11 +18,13 @@ struct ImageRowItem: View { private let status: StatusData private let attachmentData: AttachmentData + private let imageFromCache: Bool @State private var uiImage: UIImage? @State private var showThumbImage = false @State private var cancelled = true @State private var error: Error? + @State private var opacity = 1.0 @State private var isFavourited = false private let onImageDownloaded: (Double, Double) -> Void @@ -33,6 +36,9 @@ struct ImageRowItem: View { if let imageData = attachmentData.data { self.uiImage = UIImage(data: imageData) + self.imageFromCache = true + } else { + self.imageFromCache = ImagePipeline.shared.cache.containsCachedImage(for: ImageRequest(url: attachmentData.url)) } } @@ -57,9 +63,27 @@ struct ImageRowItem: View { } } } + .opacity(self.opacity) + .onAppear { + if self.imageFromCache == false { + self.opacity = 0.0 + withAnimation { + self.opacity = 1.0 + } + } + } } else { self.imageContainerView(uiImage: uiImage) .imageContextMenu(statusData: self.status, attachmentData: self.attachmentData, uiImage: uiImage) + .opacity(self.opacity) + .onAppear { + if self.imageFromCache == false { + self.opacity = 0.0 + withAnimation { + self.opacity = 1.0 + } + } + } } } else { if cancelled { diff --git a/Vernissage/Widgets/ImageRowItemAsync.swift b/Vernissage/Widgets/ImageRowItemAsync.swift index 47ee8f8..45a79d3 100644 --- a/Vernissage/Widgets/ImageRowItemAsync.swift +++ b/Vernissage/Widgets/ImageRowItemAsync.swift @@ -5,9 +5,10 @@ // import SwiftUI +import Nuke +import NukeUI import PixelfedKit import ClientKit -import NukeUI import ServicesKit import EnvironmentKit import WidgetsKit @@ -20,8 +21,10 @@ struct ImageRowItemAsync: View { private var statusViewModel: StatusModel private var attachment: AttachmentModel private let showAvatar: Bool + private let imageFromCache: Bool @State private var showThumbImage = false + @State private var opacity = 1.0 @State private var isFavourited = false private let onImageDownloaded: (Double, Double) -> Void @@ -33,6 +36,8 @@ struct ImageRowItemAsync: View { self.statusViewModel = statusViewModel self.attachment = attachment self.onImageDownloaded = onImageDownloaded + + self.imageFromCache = ImagePipeline.shared.cache.containsCachedImage(for: ImageRequest(url: attachment.url)) } var body: some View { @@ -60,20 +65,36 @@ struct ImageRowItemAsync: View { } } } + .opacity(self.opacity) .onAppear { if let uiImage = state.imageResponse?.image { self.recalculateSizeOfDownloadedImage(uiImage: uiImage) } + + if self.imageFromCache == false { + self.opacity = 0.0 + withAnimation { + self.opacity = 1.0 + } + } } } else { self.imageContainerView(image: image) .imageContextMenu(statusModel: self.statusViewModel, attachmentModel: self.attachment, uiImage: state.imageResponse?.image) + .opacity(self.opacity) .onAppear { if let uiImage = state.imageResponse?.image { self.recalculateSizeOfDownloadedImage(uiImage: uiImage) } + + if self.imageFromCache == false { + self.opacity = 0.0 + withAnimation { + self.opacity = 1.0 + } + } } } } else if state.error != nil {