RelayPicView.swift (3898B)
1 // 2 // RelayPicView.swift 3 // damus 4 // 5 // Created by eric on 9/2/23. 6 // 7 8 import SwiftUI 9 import Kingfisher 10 11 struct FailedRelayImage: View { 12 let url: URL? 13 14 var body: some View { 15 let abbrv = String(url?.host()?.first?.uppercased() ?? "R") 16 Text(abbrv) 17 .font(.system(size: 40, weight: .bold)) 18 } 19 } 20 21 struct InnerRelayPicView: View { 22 let url: URL? 23 let size: CGFloat 24 let highlight: Highlight 25 let disable_animation: Bool 26 @State var failedImage: Bool = false 27 28 func Placeholder(url: URL?) -> some View { 29 ZStack { 30 RoundedRectangle(cornerRadius: 15) 31 .frame(width: size, height: size) 32 .foregroundColor(DamusColors.adaptableGrey) 33 .overlay(RoundedRectangle(cornerRadius: 15).stroke(highlight_color(highlight), lineWidth: pfp_line_width(highlight))) 34 .padding(2) 35 36 FailedRelayImage(url: url) 37 } 38 } 39 40 var body: some View { 41 ZStack { 42 Color(uiColor: .secondarySystemBackground) 43 44 if let url { 45 KFAnimatedImage(url) 46 .imageContext(.pfp, disable_animation: disable_animation) 47 .onFailure { _ in 48 failedImage = true 49 } 50 .cancelOnDisappear(true) 51 .configure { view in 52 view.framePreloadCount = 3 53 } 54 .placeholder { _ in 55 Placeholder(url: url) 56 } 57 .scaledToFit() 58 } else { 59 FailedRelayImage(url: nil) 60 } 61 } 62 .frame(width: size, height: size) 63 .clipShape(RoundedRectangle(cornerRadius: 15)) 64 .overlay(RoundedRectangle(cornerRadius: 15).stroke(.gray.opacity(0.5), lineWidth: 0.5)) 65 } 66 } 67 68 struct RelayPicView: View { 69 let relay: RelayURL 70 let icon: String? 71 let size: CGFloat 72 let highlight: Highlight 73 let disable_animation: Bool 74 75 init(relay: RelayURL, icon: String? = nil, size: CGFloat, highlight: Highlight, disable_animation: Bool) { 76 self.relay = relay 77 self.icon = icon 78 self.size = size 79 self.highlight = highlight 80 self.disable_animation = disable_animation 81 } 82 83 var relay_url: URL? { 84 get_relay_url(relay: relay, icon: icon) 85 } 86 87 var body: some View { 88 InnerRelayPicView(url: relay_url, size: size, highlight: highlight, disable_animation: disable_animation) 89 } 90 } 91 92 func extract_tld(_ host: String) -> String { 93 let parts = host.split(separator: ".") 94 95 if parts.count >= 3 { 96 let last_3 = parts.suffix(3) 97 if parts[1] == "co" && parts[2] == "uk" { 98 return String(last_3.joined(separator: ".")) 99 } else { 100 return String(parts.suffix(2).joined(separator: ".")) 101 } 102 } else if parts.count == 2 { 103 return host 104 } 105 106 return host 107 } 108 109 func get_relay_url(relay: RelayURL, icon: String?) -> URL? { 110 var favicon = relay.absoluteString + "/favicon.ico" 111 let tld = extract_tld(relay.absoluteString) 112 if tld != relay.absoluteString { 113 favicon = "https://" + tld + "/favicon.ico" 114 } 115 let pic = icon ?? favicon 116 return URL(string: pic) 117 } 118 119 struct RelayPicView_Previews: PreviewProvider { 120 static var previews: some View { 121 VStack { 122 RelayPicView(relay: RelayURL("wss://relay.damus.io")!, size: 55, highlight: .none, disable_animation: false) 123 RelayPicView(relay: RelayURL("wss://nostr.wine")!, size: 55, highlight: .none, disable_animation: false) 124 RelayPicView(relay: RelayURL("wss://nos.lol")!, size: 55, highlight: .none, disable_animation: false) 125 RelayPicView(relay: RelayURL("wss://fail.com")!, size: 55, highlight: .none, disable_animation: false) 126 } 127 } 128 } 129