Add useful view for note-not-found state in quoted notes
Changelog-Added: Added a view for quotes notes that could not be loaded, including actionable items Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit is contained in:
@@ -15,7 +15,8 @@ struct EventLoaderView<Content: View>: View {
|
|||||||
let event_id: NoteId
|
let event_id: NoteId
|
||||||
let relayHints: [RelayURL]
|
let relayHints: [RelayURL]
|
||||||
@State var event: NostrEvent?
|
@State var event: NostrEvent?
|
||||||
@State var subscription_uuid: String = UUID().description
|
@State private var eventNotFound: Bool = false
|
||||||
|
@State private var isReloading: Bool = false
|
||||||
let content: (NostrEvent) -> Content
|
let content: (NostrEvent) -> Content
|
||||||
|
|
||||||
/// Creates an event loader view.
|
/// Creates an event loader view.
|
||||||
@@ -34,6 +35,17 @@ struct EventLoaderView<Content: View>: View {
|
|||||||
_event = State(initialValue: event)
|
_event = State(initialValue: event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Loads the event from nostrdb or the network using relay hints or the default relay pool.
|
||||||
|
///
|
||||||
|
/// This method attempts to fetch the event via `nostrNetwork.reader.lookup`, which first checks
|
||||||
|
/// nostrdb for a cached copy, then queries the network if not found locally. Network queries use
|
||||||
|
/// either the specified relay hints (if provided) or the user's relay pool (if no hints are provided).
|
||||||
|
/// On success, sets `event` and clears `eventNotFound`. On failure, sets `eventNotFound` to true.
|
||||||
|
///
|
||||||
|
/// Side effects:
|
||||||
|
/// - Updates `event` with the fetched event on success
|
||||||
|
/// - Updates `eventNotFound` flag based on the result
|
||||||
|
/// - Logs debug information when relay hints are used
|
||||||
func load() async {
|
func load() async {
|
||||||
let targetRelays = relayHints.isEmpty ? nil : relayHints
|
let targetRelays = relayHints.isEmpty ? nil : relayHints
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
@@ -42,7 +54,14 @@ struct EventLoaderView<Content: View>: View {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
let lender = try? await damus_state.nostrNetwork.reader.lookup(noteId: self.event_id, to: targetRelays)
|
let lender = try? await damus_state.nostrNetwork.reader.lookup(noteId: self.event_id, to: targetRelays)
|
||||||
lender?.justUseACopy({ event = $0 })
|
if let foundEvent = lender?.justGetACopy() {
|
||||||
|
event = foundEvent
|
||||||
|
eventNotFound = false
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Handle nil case: event was not found
|
||||||
|
eventNotFound = true
|
||||||
|
}
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if let targetRelays, !targetRelays.isEmpty {
|
if let targetRelays, !targetRelays.isEmpty {
|
||||||
print("[relay-hints] EventLoaderView: Event \(event_id.hex().prefix(8))... loaded: \(event != nil)")
|
print("[relay-hints] EventLoaderView: Event \(event_id.hex().prefix(8))... loaded: \(event != nil)")
|
||||||
@@ -50,10 +69,27 @@ struct EventLoaderView<Content: View>: View {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retries loading the event and displays loading state during the operation.
|
||||||
|
///
|
||||||
|
/// This method sets the `isReloading` flag to true, calls `load()`, and resets
|
||||||
|
/// the flag when complete. It is typically triggered by user action (e.g., "Try Again" button).
|
||||||
|
///
|
||||||
|
/// Side effects:
|
||||||
|
/// - Updates `isReloading` to true during the operation
|
||||||
|
/// - Delegates to `load()`, which updates `event` and `eventNotFound`
|
||||||
|
/// - Resets `isReloading` to false after completion
|
||||||
|
func retry() async {
|
||||||
|
isReloading = true
|
||||||
|
await load()
|
||||||
|
isReloading = false
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
if let event {
|
if let event {
|
||||||
self.content(event)
|
self.content(event)
|
||||||
|
} else if eventNotFound {
|
||||||
|
not_found
|
||||||
} else {
|
} else {
|
||||||
ProgressView().padding()
|
ProgressView().padding()
|
||||||
}
|
}
|
||||||
@@ -65,6 +101,47 @@ struct EventLoaderView<Content: View>: View {
|
|||||||
await self.load()
|
await self.load()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var not_found: some View {
|
||||||
|
VStack(spacing: 0) {
|
||||||
|
LoadableNostrEventView.SomethingWrong(
|
||||||
|
imageSystemName: "questionmark.app",
|
||||||
|
heading: NSLocalizedString("Note not found", comment: "Heading for the event loader view in a not found error state."),
|
||||||
|
description: NSLocalizedString("This note may have been deleted, or it might not be available on the relays you're connected to.", comment: "Text for the event loader view when it is unable to find the note the user is looking for"),
|
||||||
|
advice: NSLocalizedString("Try checking your internet connection, expanding your relay list, or contacting the person who quoted this note.", comment: "Tips on what to do if a quoted note cannot be found.")
|
||||||
|
)
|
||||||
|
|
||||||
|
Button(action: {
|
||||||
|
Task {
|
||||||
|
await retry()
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
HStack {
|
||||||
|
if !isReloading {
|
||||||
|
Image(systemName: "arrow.clockwise")
|
||||||
|
Text("Try Again", comment: "Button label to retry loading a note that was not found")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ProgressView()
|
||||||
|
Text("Retrying…", comment: "Button label for the retry-in-progress state when loading a note")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.font(.headline)
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.padding(.horizontal, 20)
|
||||||
|
.padding(.vertical, 12)
|
||||||
|
.background(Color.secondary)
|
||||||
|
.cornerRadius(10)
|
||||||
|
}
|
||||||
|
.disabled(isReloading)
|
||||||
|
.opacity(isReloading ? 0.6 : 1.0)
|
||||||
|
.padding(.bottom, 20)
|
||||||
|
}
|
||||||
|
.overlay(
|
||||||
|
RoundedRectangle(cornerRadius: 12)
|
||||||
|
.stroke(Color.secondary.opacity(0.3), lineWidth: 1)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user