relays: update relay view to use new design
Changelog-Changed: Updated relay view Closes: https://github.com/damus-io/damus/pull/1543
This commit is contained in:
committed by
William Casarin
parent
bfda0d1b74
commit
c4dfae9ede
@@ -8,33 +8,148 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct AddRelayView: View {
|
struct AddRelayView: View {
|
||||||
@Binding var relay: String
|
let state: DamusState
|
||||||
|
@State var new_relay: String = ""
|
||||||
|
@State var relayAddErrorTitle: String? = nil
|
||||||
|
@State var relayAddErrorMessage: String? = nil
|
||||||
|
|
||||||
|
@Environment(\.dismiss) var dismiss
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack(alignment: .leading) {
|
VStack {
|
||||||
HStack{
|
Text("Add relay", comment: "Title text to indicate user to an add a relay.")
|
||||||
TextField(NSLocalizedString("wss://some.relay.com", comment: "Placeholder example for relay server address."), text: $relay)
|
.font(.system(size: 20, weight: .bold))
|
||||||
.padding(2)
|
.padding(.vertical)
|
||||||
.padding(.leading, 25)
|
|
||||||
|
Divider()
|
||||||
|
.padding(.bottom)
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
Label("", image: "copy2")
|
||||||
|
.onTapGesture {
|
||||||
|
if let pastedrelay = UIPasteboard.general.string {
|
||||||
|
self.new_relay = pastedrelay
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TextField(NSLocalizedString("wss://some.relay.com", comment: "Placeholder example for relay server address."), text: $new_relay)
|
||||||
.autocorrectionDisabled(true)
|
.autocorrectionDisabled(true)
|
||||||
.textInputAutocapitalization(.never)
|
.textInputAutocapitalization(.never)
|
||||||
|
|
||||||
Label("", image: "close-circle")
|
Label("", image: "close-circle")
|
||||||
.foregroundColor(.accentColor)
|
.foregroundColor(.accentColor)
|
||||||
.padding(.trailing, -25.0)
|
.opacity((new_relay == "") ? 0.0 : 1.0)
|
||||||
.opacity((relay == "") ? 0.0 : 1.0)
|
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
self.relay = ""
|
self.new_relay = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.padding(10)
|
||||||
|
.background(.secondary.opacity(0.2))
|
||||||
|
.cornerRadius(10)
|
||||||
|
|
||||||
Label("", image: "copy2")
|
if let errorMessage = relayAddErrorMessage {
|
||||||
.padding(.leading, -10)
|
VStack(spacing: 0) {
|
||||||
.onTapGesture {
|
HStack(alignment: .top) {
|
||||||
if let pastedrelay = UIPasteboard.general.string {
|
Text(relayAddErrorTitle ?? "Error")
|
||||||
self.relay = pastedrelay
|
.bold()
|
||||||
|
.foregroundColor(DamusColors.dangerSecondary)
|
||||||
|
.padding(.leading)
|
||||||
|
Spacer()
|
||||||
|
Button(action: {
|
||||||
|
relayAddErrorTitle = nil // Clear error title
|
||||||
|
relayAddErrorMessage = nil // Clear error message
|
||||||
|
self.new_relay = ""
|
||||||
|
}, label: {
|
||||||
|
Image("close")
|
||||||
|
.frame(width: 20, height: 20)
|
||||||
|
.foregroundColor(DamusColors.dangerSecondary)
|
||||||
|
})
|
||||||
|
.padding(.trailing)
|
||||||
|
}
|
||||||
|
|
||||||
|
Text(errorMessage)
|
||||||
|
.foregroundColor(DamusColors.dangerSecondary)
|
||||||
|
.padding(.top, 10)
|
||||||
|
}
|
||||||
|
.frame(minWidth: 300, maxWidth: .infinity, minHeight: 120, alignment: .center)
|
||||||
|
.background {
|
||||||
|
RoundedRectangle(cornerRadius: 12)
|
||||||
|
.fill(DamusColors.dangerBorder, strokeBorder: .gray.opacity(0.5), lineWidth: 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Button(action: {
|
||||||
|
if new_relay.starts(with: "wss://") == false && new_relay.starts(with: "ws://") == false {
|
||||||
|
new_relay = "wss://" + new_relay
|
||||||
|
}
|
||||||
|
|
||||||
|
if new_relay.hasSuffix("/") {
|
||||||
|
new_relay.removeLast();
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let url = RelayURL(new_relay),
|
||||||
|
let ev = state.contacts.event,
|
||||||
|
let keypair = state.keypair.to_full() else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let info = RelayInfo.rw
|
||||||
|
let descriptor = RelayDescriptor(url: url, info: info)
|
||||||
|
|
||||||
|
do {
|
||||||
|
try state.pool.add_relay(descriptor)
|
||||||
|
relayAddErrorTitle = nil // Clear error title
|
||||||
|
relayAddErrorMessage = nil // Clear error message
|
||||||
|
} catch RelayError.RelayAlreadyExists {
|
||||||
|
relayAddErrorTitle = NSLocalizedString("Duplicate relay", comment: "Title of the duplicate relay error message.")
|
||||||
|
relayAddErrorMessage = NSLocalizedString("The relay you are trying to add is already added.\nYou're all set!", comment: "An error message that appears when the user attempts to add a relay that has already been added.")
|
||||||
|
return
|
||||||
|
} catch {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
state.pool.connect(to: [new_relay])
|
||||||
|
|
||||||
|
guard let new_ev = add_relay(ev: ev, keypair: keypair, current_relays: state.pool.our_descriptors, relay: new_relay, info: info) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
process_contact_event(state: state, ev: ev)
|
||||||
|
|
||||||
|
state.pool.send(.event(new_ev))
|
||||||
|
|
||||||
|
new_relay = ""
|
||||||
|
|
||||||
|
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
|
||||||
|
|
||||||
|
dismiss()
|
||||||
|
}) {
|
||||||
|
HStack {
|
||||||
|
Text(verbatim: "Add relay")
|
||||||
|
.bold()
|
||||||
|
}
|
||||||
|
.frame(minWidth: 300, maxWidth: .infinity, alignment: .center)
|
||||||
|
}
|
||||||
|
.buttonStyle(GradientButtonStyle(padding: 10))
|
||||||
|
//.disabled(!new_relay.isValidURL) <--- TODO
|
||||||
|
.padding(.vertical)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// This works sometimes, in certain cases where the relay is valid it won't allow the user to add it
|
||||||
|
// Needs improvement
|
||||||
|
extension String {
|
||||||
|
var isValidURL: Bool {
|
||||||
|
let detector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
|
||||||
|
if let match = detector.firstMatch(in: self, options: [], range: NSRange(location: 0, length: self.utf16.count)) {
|
||||||
|
// it is a link, if the match covers the whole string
|
||||||
|
return match.range.length == self.utf16.count
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,6 +158,6 @@ struct AddRelayView_Previews: PreviewProvider {
|
|||||||
@State static var relay: String = ""
|
@State static var relay: String = ""
|
||||||
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
AddRelayView(relay: $relay)
|
AddRelayView(state: test_damus_state())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,64 +12,50 @@ struct RecommendedRelayView: View {
|
|||||||
let relay: String
|
let relay: String
|
||||||
let add_button: Bool
|
let add_button: Bool
|
||||||
|
|
||||||
|
@ObservedObject private var model_cache: RelayModelCache
|
||||||
|
|
||||||
@Binding var showActionButtons: Bool
|
@Binding var showActionButtons: Bool
|
||||||
|
|
||||||
init(damus: DamusState, relay: String, add_button: Bool = true, showActionButtons: Binding<Bool>) {
|
init(damus: DamusState, relay: String, add_button: Bool = true, showActionButtons: Binding<Bool>) {
|
||||||
self.damus = damus
|
self.damus = damus
|
||||||
self.relay = relay
|
self.relay = relay
|
||||||
self.add_button = add_button
|
self.add_button = add_button
|
||||||
|
self.model_cache = damus.relay_model_cache
|
||||||
self._showActionButtons = showActionButtons
|
self._showActionButtons = showActionButtons
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var recommended: [RelayDescriptor] {
|
||||||
|
let rs: [RelayDescriptor] = []
|
||||||
|
return BOOTSTRAP_RELAYS.reduce(into: rs) { xs, x in
|
||||||
|
if damus.pool.get_relay(x) == nil, let url = RelayURL(x) {
|
||||||
|
xs.append(RelayDescriptor(url: url, info: .rw))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack {
|
VStack {
|
||||||
|
let meta = model_cache.model(with_relay_id: relay)?.metadata
|
||||||
|
|
||||||
|
RelayPicView(relay: relay, icon: meta?.icon, size: 70, highlight: .none, disable_animation: false)
|
||||||
|
if let meta = damus.relay_model_cache.model(with_relay_id: relay)?.metadata {
|
||||||
|
NavigationLink(value: Route.RelayDetail(relay: relay, metadata: meta)){
|
||||||
|
EmptyView()
|
||||||
|
}
|
||||||
|
.opacity(0.0)
|
||||||
|
.disabled(showActionButtons)
|
||||||
|
}
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
if let keypair = damus.keypair.to_full() {
|
Text(meta?.name ?? relay.hostname ?? relay)
|
||||||
if showActionButtons && add_button {
|
.lineLimit(1)
|
||||||
AddButton(keypair: keypair, showText: false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RelayType(is_paid: damus.relay_model_cache.model(with_relay_id: relay)?.metadata.is_paid ?? false)
|
|
||||||
|
|
||||||
Text(relay).layoutPriority(1)
|
|
||||||
|
|
||||||
if let meta = damus.relay_model_cache.model(with_relay_id: relay)?.metadata {
|
|
||||||
NavigationLink(value: Route.RelayDetail(relay: relay, metadata: meta)){
|
|
||||||
EmptyView()
|
|
||||||
}
|
|
||||||
.opacity(0.0)
|
|
||||||
.disabled(showActionButtons)
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
Image("info")
|
|
||||||
.resizable()
|
|
||||||
.frame(width: 20, height: 20)
|
|
||||||
.foregroundColor(Color.accentColor)
|
|
||||||
} else {
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
Image("question")
|
|
||||||
.resizable()
|
|
||||||
.frame(width: 20, height: 20)
|
|
||||||
.foregroundColor(.gray)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
.contextMenu {
|
||||||
.swipeActions {
|
CopyAction(relay: relay)
|
||||||
if add_button {
|
|
||||||
if let keypair = damus.keypair.to_full() {
|
|
||||||
AddButton(keypair: keypair, showText: false)
|
|
||||||
.tint(.accentColor)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
.contextMenu {
|
|
||||||
CopyAction(relay: relay)
|
|
||||||
|
|
||||||
if let keypair = damus.keypair.to_full() {
|
if let keypair = damus.keypair.to_full() {
|
||||||
AddButton(keypair: keypair, showText: true)
|
AddButton(keypair: keypair)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,19 +68,14 @@ struct RecommendedRelayView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddButton(keypair: FullKeypair, showText: Bool) -> some View {
|
func AddButton(keypair: FullKeypair) -> some View {
|
||||||
Button(action: {
|
Button(action: {
|
||||||
add_action(keypair: keypair)
|
add_action(keypair: keypair)
|
||||||
}) {
|
}) {
|
||||||
if showText {
|
Text(NSLocalizedString("Add", comment: "Button to add relay server to list."))
|
||||||
Text(NSLocalizedString("Connect", comment: "Button to connect to recommended relay server."))
|
.padding(10)
|
||||||
}
|
|
||||||
Image("plus-circle")
|
|
||||||
.resizable()
|
|
||||||
.frame(width: 20, height: 20)
|
|
||||||
.foregroundColor(.accentColor)
|
|
||||||
.padding(.leading, 5)
|
|
||||||
}
|
}
|
||||||
|
.buttonStyle(NeutralButtonStyle())
|
||||||
}
|
}
|
||||||
|
|
||||||
func add_action(keypair: FullKeypair) {
|
func add_action(keypair: FullKeypair) {
|
||||||
|
|||||||
@@ -9,10 +9,9 @@ import SwiftUI
|
|||||||
|
|
||||||
struct RelayConfigView: View {
|
struct RelayConfigView: View {
|
||||||
let state: DamusState
|
let state: DamusState
|
||||||
@State var new_relay: String = ""
|
|
||||||
@State var relays: [RelayDescriptor]
|
@State var relays: [RelayDescriptor]
|
||||||
@State private var showActionButtons = false
|
@State private var showActionButtons = false
|
||||||
@State var relayAddErrorMessage: String? = nil
|
@State var show_add_relay: Bool = false
|
||||||
|
|
||||||
@Environment(\.dismiss) var dismiss
|
@Environment(\.dismiss) var dismiss
|
||||||
|
|
||||||
@@ -41,118 +40,69 @@ struct RelayConfigView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var MainContent: some View {
|
var MainContent: some View {
|
||||||
Form {
|
VStack {
|
||||||
Section {
|
Divider()
|
||||||
AddRelayView(relay: $new_relay)
|
|
||||||
} header: {
|
|
||||||
HStack {
|
|
||||||
Text(NSLocalizedString("Connect To Relay", comment: "Label for section for adding a relay server."))
|
|
||||||
.font(.system(size: 18, weight: .heavy))
|
|
||||||
.padding(.bottom, 5)
|
|
||||||
}
|
|
||||||
} footer: {
|
|
||||||
VStack {
|
|
||||||
HStack {
|
|
||||||
Spacer()
|
|
||||||
if !new_relay.isEmpty {
|
|
||||||
Button(NSLocalizedString("Cancel", comment: "Button to cancel out of view adding user inputted relay.")) {
|
|
||||||
new_relay = ""
|
|
||||||
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
|
|
||||||
}
|
|
||||||
.font(.system(size: 14, weight: .bold))
|
|
||||||
.frame(width: 80, height: 30)
|
|
||||||
.foregroundColor(.white)
|
|
||||||
.background(LINEAR_GRADIENT)
|
|
||||||
.clipShape(Capsule())
|
|
||||||
.padding(EdgeInsets(top: 15, leading: 0, bottom: 0, trailing: 0))
|
|
||||||
|
|
||||||
Button(NSLocalizedString("Add", comment: "Button to confirm adding user inputted relay.")) {
|
|
||||||
|
|
||||||
if new_relay.starts(with: "wss://") == false && new_relay.starts(with: "ws://") == false {
|
|
||||||
new_relay = "wss://" + new_relay
|
|
||||||
}
|
|
||||||
|
|
||||||
if new_relay.hasSuffix("/") {
|
|
||||||
new_relay.removeLast();
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let url = RelayURL(new_relay),
|
|
||||||
let ev = state.contacts.event,
|
|
||||||
let keypair = state.keypair.to_full() else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let info = RelayInfo.rw
|
|
||||||
let descriptor = RelayDescriptor(url: url, info: info)
|
|
||||||
|
|
||||||
do {
|
|
||||||
try state.pool.add_relay(descriptor)
|
|
||||||
relayAddErrorMessage = nil // Clear error message
|
|
||||||
} catch RelayError.RelayAlreadyExists {
|
|
||||||
relayAddErrorMessage = NSLocalizedString("This relay is already in your list", comment: "An error message that appears when the user attempts to add a relay that has already been added.")
|
|
||||||
return
|
|
||||||
} catch {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
state.pool.connect(to: [new_relay])
|
|
||||||
|
|
||||||
guard let new_ev = add_relay(ev: ev, keypair: keypair, current_relays: state.pool.our_descriptors, relay: new_relay, info: info) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
process_contact_event(state: state, ev: ev)
|
|
||||||
|
|
||||||
state.pool.send(.event(new_ev))
|
|
||||||
|
|
||||||
new_relay = ""
|
|
||||||
|
|
||||||
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
|
|
||||||
}
|
|
||||||
.font(.system(size: 14, weight: .bold))
|
|
||||||
.frame(width: 80, height: 30)
|
|
||||||
.foregroundColor(.white)
|
|
||||||
.background(LINEAR_GRADIENT)
|
|
||||||
.clipShape(Capsule())
|
|
||||||
.padding(EdgeInsets(top: 15, leading: 0, bottom: 0, trailing: 0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let errorMessage = relayAddErrorMessage {
|
|
||||||
HStack {
|
|
||||||
Spacer()
|
|
||||||
Text(errorMessage)
|
|
||||||
.foregroundColor(Color.red)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Section {
|
|
||||||
List(Array(relays), id: \.url) { relay in
|
|
||||||
RelayView(state: state, relay: relay.url.id, showActionButtons: $showActionButtons)
|
|
||||||
}
|
|
||||||
} header: {
|
|
||||||
HStack {
|
|
||||||
Text(NSLocalizedString("Connected Relays", comment: "Section title for relay servers that are connected."))
|
|
||||||
.font(.system(size: 18, weight: .heavy))
|
|
||||||
.padding(.bottom, 5)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if recommended.count > 0 {
|
if recommended.count > 0 {
|
||||||
Section {
|
VStack {
|
||||||
List(recommended, id: \.url) { r in
|
Text("Recommended relays")
|
||||||
RecommendedRelayView(damus: state, relay: r.url.id, showActionButtons: $showActionButtons)
|
.foregroundStyle(DamusLightGradient.gradient)
|
||||||
|
.padding(10)
|
||||||
|
.background {
|
||||||
|
RoundedRectangle(cornerRadius: 15)
|
||||||
|
.stroke(DamusLightGradient.gradient)
|
||||||
|
}
|
||||||
|
.padding(.vertical)
|
||||||
|
|
||||||
|
HStack(spacing: 20) {
|
||||||
|
ForEach(recommended, id: \.url) { r in
|
||||||
|
RecommendedRelayView(damus: state, relay: r.url.id, showActionButtons: $showActionButtons)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} header: {
|
.padding()
|
||||||
Text(NSLocalizedString("Recommended Relays", comment: "Section title for recommend relay servers that could be added as part of configuration"))
|
|
||||||
.font(.system(size: 18, weight: .heavy))
|
|
||||||
.padding(.bottom, 5)
|
|
||||||
}
|
}
|
||||||
|
.frame(minWidth: 250, maxWidth: .infinity, minHeight: 250, alignment: .center)
|
||||||
|
.background {
|
||||||
|
RoundedRectangle(cornerRadius: 12)
|
||||||
|
.fill(DamusLightGradient.gradient.opacity(0.15), strokeBorder: DamusLightGradient.gradient, lineWidth: 1)
|
||||||
|
}
|
||||||
|
.padding(.horizontal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
Text(NSLocalizedString("My Relays", comment: "Section title for relay servers that the user is connected to."))
|
||||||
|
.font(.system(size: 32, weight: .bold))
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Button(action: {
|
||||||
|
show_add_relay.toggle()
|
||||||
|
}) {
|
||||||
|
HStack {
|
||||||
|
Text(verbatim: "Add relay")
|
||||||
|
.padding(10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.buttonStyle(NeutralButtonStyle())
|
||||||
|
}
|
||||||
|
.padding(25)
|
||||||
|
|
||||||
|
List(Array(relays), id: \.url) { relay in
|
||||||
|
RelayView(state: state, relay: relay.url.id, showActionButtons: $showActionButtons)
|
||||||
|
}
|
||||||
|
.listStyle(PlainListStyle())
|
||||||
}
|
}
|
||||||
.navigationTitle(NSLocalizedString("Relays", comment: "Title of relays view"))
|
.navigationTitle(NSLocalizedString("Relays", comment: "Title of relays view"))
|
||||||
.navigationBarTitleDisplayMode(.large)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
|
.sheet(isPresented: $show_add_relay, onDismiss: { self.show_add_relay = false }) {
|
||||||
|
if #available(iOS 16.0, *) {
|
||||||
|
AddRelayView(state: state)
|
||||||
|
.presentationDetents([.height(300)])
|
||||||
|
.presentationDragIndicator(.visible)
|
||||||
|
} else {
|
||||||
|
AddRelayView(state: state)
|
||||||
|
}
|
||||||
|
}
|
||||||
.toolbar {
|
.toolbar {
|
||||||
if state.keypair.privkey != nil {
|
if state.keypair.privkey != nil {
|
||||||
if showActionButtons {
|
if showActionButtons {
|
||||||
|
|||||||
@@ -13,21 +13,51 @@ struct RelayStatusView: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
Group {
|
Group {
|
||||||
if connection.isConnecting {
|
if connection.isConnecting {
|
||||||
ProgressView()
|
Text("Connecting")
|
||||||
|
.font(.caption)
|
||||||
|
.frame(height: 20)
|
||||||
|
.padding(.horizontal, 10)
|
||||||
|
.foregroundColor(DamusColors.warning)
|
||||||
|
.background(DamusColors.warningQuaternary)
|
||||||
|
.cornerRadius(20)
|
||||||
|
.overlay(
|
||||||
|
RoundedRectangle(cornerRadius: 20)
|
||||||
|
.stroke(DamusColors.warningBorder, lineWidth: 1)
|
||||||
|
)
|
||||||
|
} else if connection.isConnected {
|
||||||
|
Text("Online")
|
||||||
|
.font(.caption)
|
||||||
|
.frame(height: 20)
|
||||||
|
.padding(.horizontal, 10)
|
||||||
|
.foregroundColor(DamusColors.success)
|
||||||
|
.background(DamusColors.successQuaternary)
|
||||||
|
.cornerRadius(20)
|
||||||
|
.overlay(
|
||||||
|
RoundedRectangle(cornerRadius: 20)
|
||||||
|
.stroke(DamusColors.successBorder, lineWidth: 1)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
Image(connection.isConnected ? "globe" : "warning.fill")
|
Text("Error")
|
||||||
.resizable()
|
.font(.caption)
|
||||||
.foregroundColor(connection.isConnected ? .green : .red)
|
.frame(height: 20)
|
||||||
|
.padding(.horizontal, 10)
|
||||||
|
.foregroundColor(DamusColors.danger)
|
||||||
|
.background(DamusColors.dangerQuaternary)
|
||||||
|
.border(DamusColors.dangerBorder)
|
||||||
|
.cornerRadius(20)
|
||||||
|
.overlay(
|
||||||
|
RoundedRectangle(cornerRadius: 20)
|
||||||
|
.stroke(DamusColors.dangerBorder, lineWidth: 1)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(width: 20, height: 20)
|
.padding(.trailing, 20)
|
||||||
.padding(.trailing, 5)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RelayStatusView_Previews: PreviewProvider {
|
struct RelayStatusView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
let connection = test_damus_state().pool.get_relay("relay")!.connection
|
let connection = test_damus_state().pool.get_relay("wss://relay.damus.io")!.connection
|
||||||
RelayStatusView(connection: connection)
|
RelayStatusView(connection: connection)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,41 +28,35 @@ struct RelayView: View {
|
|||||||
if showActionButtons {
|
if showActionButtons {
|
||||||
RemoveButton(privkey: privkey, showText: false)
|
RemoveButton(privkey: privkey, showText: false)
|
||||||
}
|
}
|
||||||
else if let relay_connection {
|
|
||||||
RelayStatusView(connection: relay_connection)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RelayType(is_paid: state.relay_model_cache.model(with_relay_id: relay)?.metadata.is_paid ?? false)
|
let meta = model_cache.model(with_relay_id: relay)?.metadata
|
||||||
|
|
||||||
if let meta = model_cache.model(with_relay_id: relay)?.metadata {
|
RelayPicView(relay: relay, icon: meta?.icon, size: 55, highlight: .none, disable_animation: false)
|
||||||
|
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
HStack {
|
||||||
|
Text(meta?.name ?? relay)
|
||||||
|
.font(.headline)
|
||||||
|
.padding(.bottom, 2)
|
||||||
|
RelayType(is_paid: state.relay_model_cache.model(with_relay_id: relay)?.metadata.is_paid ?? false)
|
||||||
|
}
|
||||||
Text(relay)
|
Text(relay)
|
||||||
|
.font(.subheadline)
|
||||||
|
.foregroundColor(.gray)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
if let relay_connection {
|
||||||
|
RelayStatusView(connection: relay_connection)
|
||||||
.background(
|
.background(
|
||||||
NavigationLink(value: Route.RelayDetail(relay: relay, metadata: meta), label: {
|
NavigationLink(value: Route.RelayDetail(relay: relay, metadata: meta), label: {
|
||||||
EmptyView()
|
EmptyView()
|
||||||
}).opacity(0.0).disabled(showActionButtons)
|
})
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
.disabled(showActionButtons)
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
Image("info")
|
|
||||||
.resizable()
|
|
||||||
.frame(width: 20, height: 20)
|
|
||||||
.foregroundColor(Color.accentColor)
|
|
||||||
} else {
|
|
||||||
Text(relay)
|
|
||||||
.background(
|
|
||||||
NavigationLink(value: Route.RelayDetail(relay: relay, metadata: nil), label: {
|
|
||||||
EmptyView()
|
|
||||||
}).opacity(0.0).disabled(showActionButtons)
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
Image("question")
|
|
||||||
.resizable()
|
|
||||||
.frame(width: 20, height: 20)
|
|
||||||
.foregroundColor(.gray)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user