The introduction of iOS 18 brought a new bug that made `KFAnimatedImage` not recognize tap gestures and become unclickable. (https://github.com/onevcat/Kingfisher/issues/2295) This commit addresses the issue with a workaround found here: https://github.com/onevcat/Kingfisher/issues/2046#issuecomment-1554068070 The workaround was suggested by the author of the library to fix a slightly different issue, but that property seems to work for our purposes. The issue is addressed by adding a `contentShape` property to usages of `KFAnimatedImage`, in order to make them clickable. A custom modifier was created to make the solution less obscure and more obvious. Furthermore, one empty tap gesture handler was removed as it was preventing other tap gesture handlers on the image carousel from being triggered on iOS 18 Testing ------- PASS Configurations: - iPhone 13 mini on iOS 18.0 - iPhone SE simulator on iOS 17.5 Damus: This commit Coverage: - Check that the following views are clickable: - Images in the carousel - Profile picture on notes - Profile picture on thread comments - Profile picture on profile page Changelog-Fixed: Fix items that became unclickable on iOS 18 Closes: https://github.com/damus-io/damus/issues/2342 Closes: https://github.com/damus-io/damus/issues/2370 Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
131 lines
3.8 KiB
Swift
131 lines
3.8 KiB
Swift
//
|
|
// RelayPicView.swift
|
|
// damus
|
|
//
|
|
// Created by eric on 9/2/23.
|
|
//
|
|
|
|
import SwiftUI
|
|
import Kingfisher
|
|
|
|
struct FailedRelayImage: View {
|
|
let url: URL?
|
|
|
|
var body: some View {
|
|
let abbrv = String(url?.host()?.first?.uppercased() ?? "R")
|
|
Text(abbrv)
|
|
.font(.system(size: 40, weight: .bold))
|
|
}
|
|
}
|
|
|
|
struct InnerRelayPicView: View {
|
|
let url: URL?
|
|
let size: CGFloat
|
|
let highlight: Highlight
|
|
let disable_animation: Bool
|
|
@State var failedImage: Bool = false
|
|
|
|
func Placeholder(url: URL?) -> some View {
|
|
ZStack {
|
|
RoundedRectangle(cornerRadius: 15)
|
|
.frame(width: size, height: size)
|
|
.foregroundColor(DamusColors.adaptableGrey)
|
|
.overlay(RoundedRectangle(cornerRadius: 15).stroke(highlight_color(highlight), lineWidth: pfp_line_width(highlight)))
|
|
.padding(2)
|
|
|
|
FailedRelayImage(url: url)
|
|
}
|
|
}
|
|
|
|
var body: some View {
|
|
ZStack {
|
|
Color(uiColor: .secondarySystemBackground)
|
|
|
|
if let url {
|
|
KFAnimatedImage(url)
|
|
.imageContext(.pfp, disable_animation: disable_animation)
|
|
.onFailure { _ in
|
|
failedImage = true
|
|
}
|
|
.cancelOnDisappear(true)
|
|
.configure { view in
|
|
view.framePreloadCount = 3
|
|
}
|
|
.placeholder { _ in
|
|
Placeholder(url: url)
|
|
}
|
|
.scaledToFit()
|
|
.kfClickable()
|
|
} else {
|
|
FailedRelayImage(url: nil)
|
|
}
|
|
}
|
|
.frame(width: size, height: size)
|
|
.clipShape(RoundedRectangle(cornerRadius: 15))
|
|
.overlay(RoundedRectangle(cornerRadius: 15).stroke(.gray.opacity(0.5), lineWidth: 0.5))
|
|
}
|
|
}
|
|
|
|
struct RelayPicView: View {
|
|
let relay: RelayURL
|
|
let icon: String?
|
|
let size: CGFloat
|
|
let highlight: Highlight
|
|
let disable_animation: Bool
|
|
|
|
init(relay: RelayURL, icon: String? = nil, size: CGFloat, highlight: Highlight, disable_animation: Bool) {
|
|
self.relay = relay
|
|
self.icon = icon
|
|
self.size = size
|
|
self.highlight = highlight
|
|
self.disable_animation = disable_animation
|
|
}
|
|
|
|
var relay_url: URL? {
|
|
get_relay_url(relay: relay, icon: icon)
|
|
}
|
|
|
|
var body: some View {
|
|
InnerRelayPicView(url: relay_url, size: size, highlight: highlight, disable_animation: disable_animation)
|
|
}
|
|
}
|
|
|
|
func extract_tld(_ host: String) -> String {
|
|
let parts = host.split(separator: ".")
|
|
|
|
if parts.count >= 3 {
|
|
let last_3 = parts.suffix(3)
|
|
if parts[1] == "co" && parts[2] == "uk" {
|
|
return String(last_3.joined(separator: "."))
|
|
} else {
|
|
return String(parts.suffix(2).joined(separator: "."))
|
|
}
|
|
} else if parts.count == 2 {
|
|
return host
|
|
}
|
|
|
|
return host
|
|
}
|
|
|
|
func get_relay_url(relay: RelayURL, icon: String?) -> URL? {
|
|
var favicon = relay.absoluteString + "/favicon.ico"
|
|
let tld = extract_tld(relay.absoluteString)
|
|
if tld != relay.absoluteString {
|
|
favicon = "https://" + tld + "/favicon.ico"
|
|
}
|
|
let pic = icon ?? favicon
|
|
return URL(string: pic)
|
|
}
|
|
|
|
struct RelayPicView_Previews: PreviewProvider {
|
|
static var previews: some View {
|
|
VStack {
|
|
RelayPicView(relay: RelayURL("wss://relay.damus.io")!, size: 55, highlight: .none, disable_animation: false)
|
|
RelayPicView(relay: RelayURL("wss://nostr.wine")!, size: 55, highlight: .none, disable_animation: false)
|
|
RelayPicView(relay: RelayURL("wss://nos.lol")!, size: 55, highlight: .none, disable_animation: false)
|
|
RelayPicView(relay: RelayURL("wss://fail.com")!, size: 55, highlight: .none, disable_animation: false)
|
|
}
|
|
}
|
|
}
|
|
|