Improve robustness of the URL handler

This commit improves reliability on the handling of
external URLs.

This was achieved through the following improvements:
1. The URL handler interface is now well-defined, with more clear inputs
   and outputs, to avoid silent failures and error paths that are hard to see
   within convoluted logic paths
2. Side effects during URL parsing were almost completely removed for
   more predictable behavior
3. Error handling logic was added to present errors to the user in a user-friendly manner,
   instead of silently failing
4. Event loading logic was moved into a special new thread view, which
   makes its own internal state evident to the user (i.e. whether
   the note is loading, loaded, or if the note could not be found)

These changes make the URL opening logic more predictable, easy to
refactor, and helps ensure the user always gets some outcome from
opening a URL, even if it means showing a "not found" or "error" screen,
to eliminate cases where nothing seems to happen.

Closes: https://github.com/damus-io/damus/issues/2429
Changelog-Fixed: Improved robustness of the URL handler
Changelog-Added: Added user-friendly error view for errors around the app that would not fit in other places
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit is contained in:
Daniel D’Aquino
2024-09-06 13:56:44 -07:00
parent 26df547605
commit 8066fa1bf8
10 changed files with 623 additions and 87 deletions

View File

@@ -7,6 +7,10 @@
import Foundation
/// General app-wide constants
///
/// ## Implementation notes:
/// - Force unwrapping in this class is generally ok, because the contents are static, and so we can easily provide guarantees that they will not crash the app.
class Constants {
//static let EXAMPLE_DEMOS: DamusState = .empty
static let DAMUS_APP_GROUP_IDENTIFIER: String = "group.com.damus"
@@ -32,6 +36,9 @@ class Constants {
static let DAMUS_WEBSITE_STAGING_URL: URL = URL(string: "https://staging.damus.io")!
static let DAMUS_WEBSITE_PRODUCTION_URL: URL = URL(string: "https://damus.io")!
// MARK: Damus Company Info
static let SUPPORT_PUBKEY: Pubkey = Pubkey(hex: "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681")!
// MARK: General constants
static let GIF_IMAGE_TYPE: String = "com.compuserve.gif"
}

View File

@@ -32,6 +32,7 @@ enum Route: Hashable {
case DeveloperSettings(settings: UserSettingsStore)
case FirstAidSettings(settings: UserSettingsStore)
case Thread(thread: ThreadModel)
case ThreadFromReference(note_reference: LoadableThreadModel.NoteReference)
case Reposts(reposts: EventsModel)
case QuoteReposts(quotes: EventsModel)
case Reactions(reactions: EventsModel)
@@ -96,6 +97,8 @@ enum Route: Hashable {
case .Thread(let thread):
ChatroomThreadView(damus: damusState, thread: thread)
//ThreadView(state: damusState, thread: thread)
case .ThreadFromReference(let note_reference):
LoadableThreadView(state: damusState, note_reference: note_reference)
case .Reposts(let reposts):
RepostsView(damus_state: damusState, model: reposts)
case .QuoteReposts(let quote_reposts):
@@ -187,6 +190,9 @@ enum Route: Hashable {
case .Thread(let threadModel):
hasher.combine("thread")
hasher.combine(threadModel.event.id)
case .ThreadFromReference(note_reference: let note_reference):
hasher.combine("thread_from_reference")
hasher.combine(note_reference)
case .Reposts(let reposts):
hasher.combine("reposts")
hasher.combine(reposts.target)