Merge ios18-release_1.10 fixes
Pull some things from the 1.10 release branch into master:
Daniel D’Aquino (1):
Fix unclickable elements
William Casarin (4):
relays: add some ping/pong and connection logs
relay: don't reconnect when we don't have to
This commit is contained in:
@@ -1113,6 +1113,8 @@
|
|||||||
D7CE1B482B0BE719002EDAD4 /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C32B93D2A9AD44700DC3548 /* Message.swift */; };
|
D7CE1B482B0BE719002EDAD4 /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C32B93D2A9AD44700DC3548 /* Message.swift */; };
|
||||||
D7CE1B492B0BE729002EDAD4 /* DisplayName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C9BB83029C0ED4F00FC4E37 /* DisplayName.swift */; };
|
D7CE1B492B0BE729002EDAD4 /* DisplayName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C9BB83029C0ED4F00FC4E37 /* DisplayName.swift */; };
|
||||||
D7D2A3812BF815D000E4B42B /* PushNotificationClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7D2A3802BF815D000E4B42B /* PushNotificationClient.swift */; };
|
D7D2A3812BF815D000E4B42B /* PushNotificationClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7D2A3802BF815D000E4B42B /* PushNotificationClient.swift */; };
|
||||||
|
D7D68FF92C9E01BE0015A515 /* KFClickable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7D68FF82C9E01B60015A515 /* KFClickable.swift */; };
|
||||||
|
D7D68FFA2C9E01BE0015A515 /* KFClickable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7D68FF82C9E01B60015A515 /* KFClickable.swift */; };
|
||||||
D7DBD41F2B02F15E002A6197 /* NostrKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFD32819DE8F00B3DE84 /* NostrKind.swift */; };
|
D7DBD41F2B02F15E002A6197 /* NostrKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFD32819DE8F00B3DE84 /* NostrKind.swift */; };
|
||||||
D7DEEF2F2A8C021E00E0C99F /* NostrEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7DEEF2E2A8C021E00E0C99F /* NostrEventTests.swift */; };
|
D7DEEF2F2A8C021E00E0C99F /* NostrEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7DEEF2E2A8C021E00E0C99F /* NostrEventTests.swift */; };
|
||||||
D7EDED152B11776B0018B19C /* LibreTranslateServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE45AF5297BB2E700C1D842 /* LibreTranslateServer.swift */; };
|
D7EDED152B11776B0018B19C /* LibreTranslateServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE45AF5297BB2E700C1D842 /* LibreTranslateServer.swift */; };
|
||||||
@@ -1962,6 +1964,7 @@
|
|||||||
D7CBD1D32B8D21DC00BFD889 /* DamusPurpleNotificationManagement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusPurpleNotificationManagement.swift; sourceTree = "<group>"; };
|
D7CBD1D32B8D21DC00BFD889 /* DamusPurpleNotificationManagement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusPurpleNotificationManagement.swift; sourceTree = "<group>"; };
|
||||||
D7CBD1D52B8D509800BFD889 /* DamusPurpleImpendingExpirationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusPurpleImpendingExpirationTests.swift; sourceTree = "<group>"; };
|
D7CBD1D52B8D509800BFD889 /* DamusPurpleImpendingExpirationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusPurpleImpendingExpirationTests.swift; sourceTree = "<group>"; };
|
||||||
D7D2A3802BF815D000E4B42B /* PushNotificationClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationClient.swift; sourceTree = "<group>"; };
|
D7D2A3802BF815D000E4B42B /* PushNotificationClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationClient.swift; sourceTree = "<group>"; };
|
||||||
|
D7D68FF82C9E01B60015A515 /* KFClickable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KFClickable.swift; sourceTree = "<group>"; };
|
||||||
D7DEEF2E2A8C021E00E0C99F /* NostrEventTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NostrEventTests.swift; sourceTree = "<group>"; };
|
D7DEEF2E2A8C021E00E0C99F /* NostrEventTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NostrEventTests.swift; sourceTree = "<group>"; };
|
||||||
D7EDED1B2B1178FE0018B19C /* NoteContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoteContent.swift; sourceTree = "<group>"; };
|
D7EDED1B2B1178FE0018B19C /* NoteContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoteContent.swift; sourceTree = "<group>"; };
|
||||||
D7EDED1D2B11797D0018B19C /* LongformEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LongformEvent.swift; sourceTree = "<group>"; };
|
D7EDED1D2B11797D0018B19C /* LongformEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LongformEvent.swift; sourceTree = "<group>"; };
|
||||||
@@ -2543,6 +2546,7 @@
|
|||||||
4C75EFA227FA576C0006080F /* Views */ = {
|
4C75EFA227FA576C0006080F /* Views */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
D7D68FF72C9E01A80015A515 /* Utils */,
|
||||||
D78DB85D2C20FE9E00F0AB12 /* Chat */,
|
D78DB85D2C20FE9E00F0AB12 /* Chat */,
|
||||||
D71AC4CA2BA8E3320076268E /* Extensions */,
|
D71AC4CA2BA8E3320076268E /* Extensions */,
|
||||||
BA3759952ABCCF360018D73B /* Camera */,
|
BA3759952ABCCF360018D73B /* Camera */,
|
||||||
@@ -3372,6 +3376,14 @@
|
|||||||
path = Extensions;
|
path = Extensions;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
D7D68FF72C9E01A80015A515 /* Utils */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
D7D68FF82C9E01B60015A515 /* KFClickable.swift */,
|
||||||
|
);
|
||||||
|
path = Utils;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
E06336A72B7582D600A88E6B /* Assets */ = {
|
E06336A72B7582D600A88E6B /* Assets */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -3808,6 +3820,7 @@
|
|||||||
B51C1CEA2B55A60A00E312A9 /* AddMuteItemView.swift in Sources */,
|
B51C1CEA2B55A60A00E312A9 /* AddMuteItemView.swift in Sources */,
|
||||||
4C5D5C992A6AF8F80024563C /* NdbNote.swift in Sources */,
|
4C5D5C992A6AF8F80024563C /* NdbNote.swift in Sources */,
|
||||||
4CF0ABF029857E9200D66079 /* Bech32Object.swift in Sources */,
|
4CF0ABF029857E9200D66079 /* Bech32Object.swift in Sources */,
|
||||||
|
D7D68FFA2C9E01BE0015A515 /* KFClickable.swift in Sources */,
|
||||||
4C3D52B8298DB5C6001C5831 /* TextEvent.swift in Sources */,
|
4C3D52B8298DB5C6001C5831 /* TextEvent.swift in Sources */,
|
||||||
4C216F362870A9A700040376 /* InputDismissKeyboard.swift in Sources */,
|
4C216F362870A9A700040376 /* InputDismissKeyboard.swift in Sources */,
|
||||||
D74AAFCF2B155D8C006CF0F4 /* ZapDataModel.swift in Sources */,
|
D74AAFCF2B155D8C006CF0F4 /* ZapDataModel.swift in Sources */,
|
||||||
@@ -4523,6 +4536,7 @@
|
|||||||
D73E5F332C6A97F4007EB227 /* ZapEvent.swift in Sources */,
|
D73E5F332C6A97F4007EB227 /* ZapEvent.swift in Sources */,
|
||||||
D73E5F342C6A97F4007EB227 /* TextEvent.swift in Sources */,
|
D73E5F342C6A97F4007EB227 /* TextEvent.swift in Sources */,
|
||||||
D73E5F352C6A97F4007EB227 /* WideEventView.swift in Sources */,
|
D73E5F352C6A97F4007EB227 /* WideEventView.swift in Sources */,
|
||||||
|
D7D68FF92C9E01BE0015A515 /* KFClickable.swift in Sources */,
|
||||||
D73E5F8A2C6AA69C007EB227 /* SideMenuView.swift in Sources */,
|
D73E5F8A2C6AA69C007EB227 /* SideMenuView.swift in Sources */,
|
||||||
D73E5F362C6A97F4007EB227 /* LongformView.swift in Sources */,
|
D73E5F362C6A97F4007EB227 /* LongformView.swift in Sources */,
|
||||||
D73E5F372C6A97F4007EB227 /* LongformPreview.swift in Sources */,
|
D73E5F372C6A97F4007EB227 /* LongformPreview.swift in Sources */,
|
||||||
|
|||||||
@@ -236,6 +236,7 @@ struct ImageCarousel<Content: View>: View {
|
|||||||
Placeholder(url: url, geo_size: geo.size, num_urls: urls.count)
|
Placeholder(url: url, geo_size: geo.size, num_urls: urls.count)
|
||||||
}
|
}
|
||||||
.aspectRatio(contentMode: filling ? .fill : .fit)
|
.aspectRatio(contentMode: filling ? .fill : .fit)
|
||||||
|
.kfClickable()
|
||||||
.position(x: geo.size.width / 2, y: geo.size.height / 2)
|
.position(x: geo.size.width / 2, y: geo.size.height / 2)
|
||||||
.tabItem {
|
.tabItem {
|
||||||
Text(url.absoluteString)
|
Text(url.absoluteString)
|
||||||
@@ -274,8 +275,14 @@ struct ImageCarousel<Content: View>: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
Medias
|
if #available(iOS 18.0, *) {
|
||||||
.onTapGesture { }
|
Medias
|
||||||
|
} else {
|
||||||
|
// An empty tap gesture recognizer is needed on iOS 17 and below to suppress other overlapping tap recognizers
|
||||||
|
// Otherwise it will both open the carousel and go to a note at the same time
|
||||||
|
Medias.onTapGesture { }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if urls.count > 1 {
|
if urls.count > 1 {
|
||||||
PageControlView(currentPage: $model.selectedIndex, numberOfPages: urls.count)
|
PageControlView(currentPage: $model.selectedIndex, numberOfPages: urls.count)
|
||||||
|
|||||||
@@ -46,9 +46,10 @@ final class RelayConnection: ObservableObject {
|
|||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
self.last_pong = .now
|
self.last_pong = .now
|
||||||
|
Log.info("Got pong from '%s'", for: .networking, self.relay_url.absoluteString)
|
||||||
self.log?.add("Successful ping")
|
self.log?.add("Successful ping")
|
||||||
} else {
|
} else {
|
||||||
print("pong failed, reconnecting \(self.relay_url.id)")
|
Log.info("Ping failed, reconnecting to '%s'", for: .networking, self.relay_url.absoluteString)
|
||||||
self.isConnected = false
|
self.isConnected = false
|
||||||
self.isConnecting = false
|
self.isConnecting = false
|
||||||
self.reconnect_with_backoff()
|
self.reconnect_with_backoff()
|
||||||
@@ -126,7 +127,7 @@ final class RelayConnection: ObservableObject {
|
|||||||
self.receive(message: message)
|
self.receive(message: message)
|
||||||
case .disconnected(let closeCode, let reason):
|
case .disconnected(let closeCode, let reason):
|
||||||
if closeCode != .normalClosure {
|
if closeCode != .normalClosure {
|
||||||
print("⚠️ Warning: RelayConnection (\(self.relay_url)) closed with code \(closeCode), reason: \(String(describing: reason))")
|
Log.error("⚠️ Warning: RelayConnection (%d) closed with code: %s", for: .networking, String(describing: closeCode), String(describing: reason))
|
||||||
}
|
}
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.isConnected = false
|
self.isConnected = false
|
||||||
@@ -134,12 +135,16 @@ final class RelayConnection: ObservableObject {
|
|||||||
self.reconnect()
|
self.reconnect()
|
||||||
}
|
}
|
||||||
case .error(let error):
|
case .error(let error):
|
||||||
print("⚠️ Warning: RelayConnection (\(self.relay_url)) error: \(error)")
|
Log.error("⚠️ Warning: RelayConnection (%s) error: %s", for: .networking, self.relay_url.absoluteString, error.localizedDescription)
|
||||||
let nserr = error as NSError
|
let nserr = error as NSError
|
||||||
if nserr.domain == NSPOSIXErrorDomain && nserr.code == 57 {
|
if nserr.domain == NSPOSIXErrorDomain && nserr.code == 57 {
|
||||||
// ignore socket not connected?
|
// ignore socket not connected?
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if nserr.domain == NSURLErrorDomain && nserr.code == -999 {
|
||||||
|
// these aren't real error, it just means task was cancelled
|
||||||
|
return
|
||||||
|
}
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.isConnected = false
|
self.isConnected = false
|
||||||
self.isConnecting = false
|
self.isConnecting = false
|
||||||
@@ -156,14 +161,21 @@ final class RelayConnection: ObservableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func reconnect_with_backoff() {
|
func reconnect_with_backoff() {
|
||||||
self.backoff *= 1.5
|
self.backoff *= 2.0
|
||||||
self.reconnect_in(after: self.backoff)
|
self.reconnect_in(after: self.backoff)
|
||||||
}
|
}
|
||||||
|
|
||||||
func reconnect() {
|
func reconnect() {
|
||||||
guard !isConnecting && !isDisabled else {
|
guard !isConnecting && !isDisabled else {
|
||||||
|
self.log?.add("Cancelling reconnect, already connecting")
|
||||||
return // we're already trying to connect or we're disabled
|
return // we're already trying to connect or we're disabled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
guard !self.isConnected else {
|
||||||
|
self.log?.add("Cancelling reconnect, already connected")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
disconnect()
|
disconnect()
|
||||||
connect()
|
connect()
|
||||||
log?.add("Reconnecting...")
|
log?.add("Reconnecting...")
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ class RelayPool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ping() {
|
func ping() {
|
||||||
|
Log.info("Pinging %d relays", for: .networking, relays.count)
|
||||||
for relay in relays {
|
for relay in relays {
|
||||||
relay.connection.ping()
|
relay.connection.ping()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ enum LogCategory: String {
|
|||||||
case nav
|
case nav
|
||||||
case render
|
case render
|
||||||
case storage
|
case storage
|
||||||
|
case networking
|
||||||
case push_notifications
|
case push_notifications
|
||||||
case damus_purple
|
case damus_purple
|
||||||
case image_uploading
|
case image_uploading
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ struct EditBannerImageView: View {
|
|||||||
Color(uiColor: .secondarySystemBackground)
|
Color(uiColor: .secondarySystemBackground)
|
||||||
}
|
}
|
||||||
.onFailureImage(defaultImage)
|
.onFailureImage(defaultImage)
|
||||||
|
.kfClickable()
|
||||||
|
|
||||||
EditPictureControl(uploader: damus_state.settings.default_media_uploader, pubkey: damus_state.pubkey, image_url: $banner_image, uploadObserver: viewModel, callback: callback)
|
EditPictureControl(uploader: damus_state.settings.default_media_uploader, pubkey: damus_state.pubkey, image_url: $banner_image, uploadObserver: viewModel, callback: callback)
|
||||||
}
|
}
|
||||||
@@ -54,6 +55,7 @@ struct InnerBannerImageView: View {
|
|||||||
Color(uiColor: .secondarySystemBackground)
|
Color(uiColor: .secondarySystemBackground)
|
||||||
}
|
}
|
||||||
.onFailureImage(defaultImage)
|
.onFailureImage(defaultImage)
|
||||||
|
.kfClickable()
|
||||||
} else {
|
} else {
|
||||||
Image(uiImage: defaultImage).resizable()
|
Image(uiImage: defaultImage).resizable()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ struct HighlightEventRef: View {
|
|||||||
FailedImage()
|
FailedImage()
|
||||||
}
|
}
|
||||||
.frame(width: 35, height: 35)
|
.frame(width: 35, height: 35)
|
||||||
|
.kfClickable()
|
||||||
.clipShape(RoundedRectangle(cornerRadius: 10))
|
.clipShape(RoundedRectangle(cornerRadius: 10))
|
||||||
.overlay(RoundedRectangle(cornerRadius: 10).stroke(.gray.opacity(0.5), lineWidth: 0.5))
|
.overlay(RoundedRectangle(cornerRadius: 10).stroke(.gray.opacity(0.5), lineWidth: 0.5))
|
||||||
.scaledToFit()
|
.scaledToFit()
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ struct HighlightLink: View {
|
|||||||
.background(DamusColors.adaptableWhite)
|
.background(DamusColors.adaptableWhite)
|
||||||
}
|
}
|
||||||
.frame(width: 35, height: 35)
|
.frame(width: 35, height: 35)
|
||||||
|
.kfClickable()
|
||||||
.clipShape(RoundedRectangle(cornerRadius: 10))
|
.clipShape(RoundedRectangle(cornerRadius: 10))
|
||||||
.scaledToFit()
|
.scaledToFit()
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ struct LongformPreviewBody: View {
|
|||||||
}
|
}
|
||||||
.aspectRatio(contentMode: .fill)
|
.aspectRatio(contentMode: .fill)
|
||||||
.frame(maxWidth: .infinity, maxHeight: header ? .infinity : 150)
|
.frame(maxWidth: .infinity, maxHeight: header ? .infinity : 150)
|
||||||
|
.kfClickable()
|
||||||
.cornerRadius(1)
|
.cornerRadius(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ struct ImageContainerView: View {
|
|||||||
view.framePreloadCount = 3
|
view.framePreloadCount = 3
|
||||||
}
|
}
|
||||||
.imageModifier(ImageHandler(handler: $image))
|
.imageModifier(ImageHandler(handler: $image))
|
||||||
|
.kfClickable()
|
||||||
.clipped()
|
.clipped()
|
||||||
.modifier(ImageContextMenuModifier(url: url, image: image, settings: settings, showShareSheet: $showShareSheet))
|
.modifier(ImageContextMenuModifier(url: url, image: image, settings: settings, showShareSheet: $showShareSheet))
|
||||||
.sheet(isPresented: $showShareSheet) {
|
.sheet(isPresented: $showShareSheet) {
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ struct ProfileImageContainerView: View {
|
|||||||
.imageModifier(ImageHandler(handler: $image))
|
.imageModifier(ImageHandler(handler: $image))
|
||||||
.clipShape(Circle())
|
.clipShape(Circle())
|
||||||
.modifier(ImageContextMenuModifier(url: url, image: image, settings: settings, showShareSheet: $showShareSheet))
|
.modifier(ImageContextMenuModifier(url: url, image: image, settings: settings, showShareSheet: $showShareSheet))
|
||||||
|
.kfClickable()
|
||||||
.sheet(isPresented: $showShareSheet) {
|
.sheet(isPresented: $showShareSheet) {
|
||||||
ShareSheet(activityItems: [url])
|
ShareSheet(activityItems: [url])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ struct EditPictureControl: View {
|
|||||||
}
|
}
|
||||||
.scaledToFill()
|
.scaledToFill()
|
||||||
.frame(width: (size ?? 25) + 10, height: (size ?? 25) + 10)
|
.frame(width: (size ?? 25) + 10, height: (size ?? 25) + 10)
|
||||||
|
.kfClickable()
|
||||||
.foregroundColor(DamusColors.white)
|
.foregroundColor(DamusColors.white)
|
||||||
.clipShape(Circle())
|
.clipShape(Circle())
|
||||||
.overlay(Circle().stroke(.white, lineWidth: 4))
|
.overlay(Circle().stroke(.white, lineWidth: 4))
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ struct InnerProfilePicView: View {
|
|||||||
}
|
}
|
||||||
.scaledToFill()
|
.scaledToFill()
|
||||||
.frame(width: size, height: size)
|
.frame(width: size, height: size)
|
||||||
|
.kfClickable()
|
||||||
.clipShape(Circle())
|
.clipShape(Circle())
|
||||||
.overlay(Circle().stroke(highlight_color(highlight), lineWidth: pfp_line_width(highlight)))
|
.overlay(Circle().stroke(highlight_color(highlight), lineWidth: pfp_line_width(highlight)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ struct EditProfilePictureView: View {
|
|||||||
view.framePreloadCount = 3
|
view.framePreloadCount = 3
|
||||||
}
|
}
|
||||||
.scaledToFill()
|
.scaledToFill()
|
||||||
|
.kfClickable()
|
||||||
|
|
||||||
EditPictureControl(uploader: damus_state?.settings.default_media_uploader ?? .nostrBuild, pubkey: pubkey, image_url: $profile_url, uploadObserver: uploadObserver, callback: callback)
|
EditPictureControl(uploader: damus_state?.settings.default_media_uploader ?? .nostrBuild, pubkey: pubkey, image_url: $profile_url, uploadObserver: uploadObserver, callback: callback)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ struct InnerRelayPicView: View {
|
|||||||
Placeholder(url: url)
|
Placeholder(url: url)
|
||||||
}
|
}
|
||||||
.scaledToFit()
|
.scaledToFit()
|
||||||
|
.kfClickable()
|
||||||
} else {
|
} else {
|
||||||
FailedRelayImage(url: nil)
|
FailedRelayImage(url: nil)
|
||||||
}
|
}
|
||||||
|
|||||||
23
damus/Views/Utils/KFClickable.swift
Normal file
23
damus/Views/Utils/KFClickable.swift
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
//
|
||||||
|
// ClickableOverlay.swift
|
||||||
|
// damus
|
||||||
|
//
|
||||||
|
// Created by Daniel D’Aquino on 2024-09-20.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
/// Applies a property that makes `KFAnimatedImage` clickable again on iOS 18+
|
||||||
|
fileprivate struct KFClickable: ViewModifier {
|
||||||
|
func body(content: Content) -> some View {
|
||||||
|
content
|
||||||
|
.contentShape(Rectangle())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension View {
|
||||||
|
/// Applies a property that makes `KFAnimatedImage` clickable again on iOS 18+
|
||||||
|
func kfClickable() -> some View {
|
||||||
|
return self.modifier(KFClickable())
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user