Add nip05 search

Changelog-Added: Added ability to lookup users by nip05 identifiers
This commit is contained in:
William Casarin
2023-03-29 19:24:06 -04:00
parent 9fef2f071a
commit 0a4e75bfec
7 changed files with 143 additions and 2 deletions

View File

@@ -0,0 +1,69 @@
// https://github.com/Tunous/DebouncedOnChange/blob/5670ea13e8ad33e9cc3197f6d13ce492dc0e46ab/Sources/DebouncedOnChange/DebouncedChangeViewModifier.swift
import SwiftUI
import Foundation
extension View {
/// Adds a modifier for this view that fires an action only when a time interval in seconds represented by
/// `debounceTime` elapses between value changes.
///
/// Each time the value changes before `debounceTime` passes, the previous action will be cancelled and the next
/// action /// will be scheduled to run after that time passes again. This mean that the action will only execute
/// after changes to the value /// stay unmodified for the specified `debounceTime` in seconds.
///
/// - Parameters:
/// - value: The value to check against when determining whether to run the closure.
/// - debounceTime: The time in seconds to wait after each value change before running `action` closure.
/// - action: A closure to run when the value changes.
/// - Returns: A view that fires an action after debounced time when the specified value changes.
public func onChange<Value>(
of value: Value,
debounceTime: TimeInterval,
perform action: @escaping (_ newValue: Value) -> Void
) -> some View where Value: Equatable {
self.modifier(DebouncedChangeViewModifier(trigger: value, debounceTime: debounceTime, action: action))
}
}
private struct DebouncedChangeViewModifier<Value>: ViewModifier where Value: Equatable {
let trigger: Value
let debounceTime: TimeInterval
let action: (Value) -> Void
@State private var debouncedTask: Task<Void, Never>?
func body(content: Content) -> some View {
content.onChange(of: trigger) { value in
debouncedTask?.cancel()
debouncedTask = Task.delayed(seconds: debounceTime) { @MainActor in
action(value)
}
}
}
}
extension Task {
/// Asynchronously runs the given `operation` in its own task after the specified number of `seconds`.
///
/// The operation will be executed after specified number of `seconds` passes. You can cancel the task earlier
/// for the operation to be skipped.
///
/// - Parameters:
/// - time: Delay time in seconds.
/// - operation: The operation to execute.
/// - Returns: Handle to the task which can be cancelled.
@discardableResult
public static func delayed(
seconds: TimeInterval,
operation: @escaping @Sendable () async -> Void
) -> Self where Success == Void, Failure == Never {
Self {
do {
try await Task<Never, Never>.sleep(nanoseconds: UInt64(seconds * 1_000_000_000))
await operation()
} catch {}
}
}
}

View File

@@ -39,11 +39,20 @@ enum NIP05Validation {
case valid
}
func validate_nip05(pubkey: String, nip05_str: String) async -> NIP05? {
struct FetchedNIP05 {
let response: NIP05Response
let nip05: NIP05Response
}
func fetch_nip05_str(nip05_str: String) async -> NIP05Response? {
guard let nip05 = NIP05.parse(nip05_str) else {
return nil
}
return await fetch_nip05(nip05: nip05)
}
func fetch_nip05(nip05: NIP05) async -> NIP05Response? {
guard let url = nip05.url else {
return nil
}
@@ -57,6 +66,18 @@ func validate_nip05(pubkey: String, nip05_str: String) async -> NIP05? {
return nil
}
return decoded
}
func validate_nip05(pubkey: String, nip05_str: String) async -> NIP05? {
guard let nip05 = NIP05.parse(nip05_str) else {
return nil
}
guard let decoded = await fetch_nip05(nip05: nip05) else {
return nil
}
guard let stored_pk = decoded.names[nip05.username] else {
return nil
}