RelayPicView.swift (3933B)
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 .kfClickable() 59 } else { 60 FailedRelayImage(url: nil) 61 } 62 } 63 .frame(width: size, height: size) 64 .clipShape(RoundedRectangle(cornerRadius: 15)) 65 .overlay(RoundedRectangle(cornerRadius: 15).stroke(.gray.opacity(0.5), lineWidth: 0.5)) 66 } 67 } 68 69 struct RelayPicView: View { 70 let relay: RelayURL 71 let icon: String? 72 let size: CGFloat 73 let highlight: Highlight 74 let disable_animation: Bool 75 76 init(relay: RelayURL, icon: String? = nil, size: CGFloat, highlight: Highlight, disable_animation: Bool) { 77 self.relay = relay 78 self.icon = icon 79 self.size = size 80 self.highlight = highlight 81 self.disable_animation = disable_animation 82 } 83 84 var relay_url: URL? { 85 get_relay_url(relay: relay, icon: icon) 86 } 87 88 var body: some View { 89 InnerRelayPicView(url: relay_url, size: size, highlight: highlight, disable_animation: disable_animation) 90 } 91 } 92 93 func extract_tld(_ host: String) -> String { 94 let parts = host.split(separator: ".") 95 96 if parts.count >= 3 { 97 let last_3 = parts.suffix(3) 98 if parts[1] == "co" && parts[2] == "uk" { 99 return String(last_3.joined(separator: ".")) 100 } else { 101 return String(parts.suffix(2).joined(separator: ".")) 102 } 103 } else if parts.count == 2 { 104 return host 105 } 106 107 return host 108 } 109 110 func get_relay_url(relay: RelayURL, icon: String?) -> URL? { 111 var favicon = relay.absoluteString + "/favicon.ico" 112 let tld = extract_tld(relay.absoluteString) 113 if tld != relay.absoluteString { 114 favicon = "https://" + tld + "/favicon.ico" 115 } 116 let pic = icon ?? favicon 117 return URL(string: pic) 118 } 119 120 struct RelayPicView_Previews: PreviewProvider { 121 static var previews: some View { 122 VStack { 123 RelayPicView(relay: RelayURL("wss://relay.damus.io")!, size: 55, highlight: .none, disable_animation: false) 124 RelayPicView(relay: RelayURL("wss://nostr.wine")!, size: 55, highlight: .none, disable_animation: false) 125 RelayPicView(relay: RelayURL("wss://nos.lol")!, size: 55, highlight: .none, disable_animation: false) 126 RelayPicView(relay: RelayURL("wss://fail.com")!, size: 55, highlight: .none, disable_animation: false) 127 } 128 } 129 } 130