ux: Relay View Improvements

This patch removes the Recommended Relay View and the old representation of recommended relays.
Adds a tab view style to the Relay Config View allowing the user to switch between their connected relays
and recommended relays. They can add and remove from the recommended view as well. For users logged in with
a pubkey the add button will no longer be displayed.

Testing
——
iPhone 15 Pro Max (17.0) Light Mode:
https://v.nostr.build/QGMZ.mp4

iPhone SE (3rd generation) (16.4) Dark Mode:
https://v.nostr.build/Wlw3.mp4
——

Changelog-Changed: Relay config view user interface

Signed-off-by: ericholguin <ericholguin@apache.org>
Link: 20240307152808.47929-1-ericholguin@apache.org
Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
ericholguin
2024-03-07 15:28:08 +00:00
committed by William Casarin
parent 122775e586
commit 0719e94fbc
9 changed files with 295 additions and 381 deletions
+100 -40
View File
@@ -10,22 +10,31 @@ import SwiftUI
struct RelayView: View {
let state: DamusState
let relay: String
let recommended: Bool
@ObservedObject private var model_cache: RelayModelCache
@State var relay_state: Bool
@Binding var showActionButtons: Bool
init(state: DamusState, relay: String, showActionButtons: Binding<Bool>) {
init(state: DamusState, relay: String, showActionButtons: Binding<Bool>, recommended: Bool) {
self.state = state
self.relay = relay
self.recommended = recommended
self.model_cache = state.relay_model_cache
_showActionButtons = showActionButtons
let relay_state = RelayView.get_relay_state(pool: state.pool, relay: relay)
self._relay_state = State(initialValue: relay_state)
}
static func get_relay_state(pool: RelayPool, relay: String) -> Bool {
return pool.get_relay(relay) == nil
}
var body: some View {
Group {
HStack {
if let privkey = state.keypair.privkey {
if showActionButtons {
if showActionButtons && !recommended {
RemoveButton(privkey: privkey, showText: false)
}
}
@@ -39,39 +48,60 @@ struct RelayView: View {
Text(meta?.name ?? relay)
.font(.headline)
.padding(.bottom, 2)
.lineLimit(1)
RelayType(is_paid: state.relay_model_cache.model(with_relay_id: relay)?.metadata.is_paid ?? false)
}
Text(relay)
.font(.subheadline)
.foregroundColor(.gray)
.lineLimit(1)
.contextMenu {
CopyAction(relay: relay)
if let privkey = state.keypair.privkey {
RemoveButton(privkey: privkey, showText: true)
}
}
}
Spacer()
if recommended {
if let keypair = state.keypair.to_full() {
VStack(alignment: .center) {
if relay_state {
AddButton(keypair: keypair)
} else {
Button(action: {
remove_action(privkey: keypair.privkey)
}) {
Text(NSLocalizedString("Added", comment: "Button to show relay server is already added to list."))
.font(.caption)
}
.buttonStyle(NeutralButtonShape.capsule.style)
.opacity(0.5)
}
}
.padding(.horizontal, 5)
}
} else {
if let relay_connection {
RelayStatusView(connection: relay_connection)
}
if let relay_connection {
RelayStatusView(connection: relay_connection)
.background(
NavigationLink(value: Route.RelayDetail(relay: relay, metadata: meta), label: {
EmptyView()
})
.buttonStyle(.plain)
.disabled(showActionButtons)
)
Image("chevron-large-right")
.resizable()
.frame(width: 15, height: 15)
.foregroundColor(.gray)
}
}
.contentShape(Rectangle())
}
.swipeActions {
if let privkey = state.keypair.privkey {
RemoveButton(privkey: privkey, showText: false)
.tint(.red)
}
.onReceive(handle_notify(.relays_changed)) { _ in
self.relay_state = RelayView.get_relay_state(pool: state.pool, relay: self.relay)
}
.contextMenu {
CopyAction(relay: relay)
if let privkey = state.keypair.privkey {
RemoveButton(privkey: privkey, showText: true)
}
.onTapGesture {
state.nav.push(route: Route.RelayDetail(relay: relay, metadata: model_cache.model(with_relay_id: relay)?.metadata))
}
}
@@ -79,6 +109,52 @@ struct RelayView: View {
state.pool.get_relay(relay)?.connection
}
func add_action(keypair: FullKeypair) {
guard let ev_before_add = state.contacts.event else {
return
}
guard let relay_url = RelayURL(relay),
let ev_after_add = add_relay(ev: ev_before_add, keypair: keypair, current_relays: state.pool.our_descriptors, relay: relay_url, info: .rw) else {
return
}
process_contact_event(state: state, ev: ev_after_add)
state.postbox.send(ev_after_add)
if let relay_metadata = make_relay_metadata(relays: state.pool.our_descriptors, keypair: keypair) {
state.postbox.send(relay_metadata)
}
}
func remove_action(privkey: Privkey) {
guard let ev = state.contacts.event else {
return
}
let descriptors = state.pool.our_descriptors
guard let keypair = state.keypair.to_full(),
let relay_url = RelayURL(relay),
let new_ev = remove_relay(ev: ev, current_relays: descriptors, keypair: keypair, relay: relay_url) else {
return
}
process_contact_event(state: state, ev: new_ev)
state.postbox.send(new_ev)
if let relay_metadata = make_relay_metadata(relays: state.pool.our_descriptors, keypair: keypair) {
state.postbox.send(relay_metadata)
}
}
func AddButton(keypair: FullKeypair) -> some View {
Button(action: {
add_action(keypair: keypair)
}) {
Text(NSLocalizedString("Add", comment: "Button to add relay server to list."))
.font(.caption)
}
.buttonStyle(NeutralButtonShape.capsule.style)
}
func CopyAction(relay: String) -> some View {
Button {
UIPasteboard.general.setValue(relay, forPasteboardType: "public.plain-text")
@@ -89,23 +165,7 @@ struct RelayView: View {
func RemoveButton(privkey: Privkey, showText: Bool) -> some View {
Button(action: {
guard let ev = state.contacts.event else {
return
}
let descriptors = state.pool.our_descriptors
guard let keypair = state.keypair.to_full(),
let relay_url = RelayURL(relay),
let new_ev = remove_relay(ev: ev, current_relays: descriptors, keypair: keypair, relay: relay_url) else {
return
}
process_contact_event(state: state, ev: new_ev)
state.postbox.send(new_ev)
if let relay_metadata = make_relay_metadata(relays: state.pool.our_descriptors, keypair: keypair) {
state.postbox.send(relay_metadata)
}
remove_action(privkey: privkey)
}) {
if showText {
Text(NSLocalizedString("Disconnect", comment: "Button to disconnect from a relay server."))
@@ -122,6 +182,6 @@ struct RelayView: View {
struct RelayView_Previews: PreviewProvider {
static var previews: some View {
RelayView(state: test_damus_state, relay: "wss://relay.damus.io", showActionButtons: .constant(false))
RelayView(state: test_damus_state, relay: "wss://relay.damus.io", showActionButtons: .constant(false), recommended: false)
}
}