~ knotless Search/
↑↓ move↵ open⇧↵ all results

grain.social/grain-ios

1 collaborator
0
1
main
55 lines · 1.7 KB Raw History
import Foundation

enum DeepLink: Equatable {
    case profile(did: String)
    case gallery(did: String, rkey: String)
    case story(did: String, rkey: String)

    static func from(url: URL) -> DeepLink? {
        // Normalize: for grain:// scheme, host is the first segment (e.g. grain://profile/did/...)
        // For https, path starts with /profile/did/...
        let segments: [String] = if url.scheme == "grain", let host = url.host {
            [host] + url.pathComponents.filter { $0 != "/" }
        } else {
            url.pathComponents.filter { $0 != "/" }
        }

        guard segments.first == "profile", segments.count >= 2 else { return nil }
        let did = segments[1]

        if segments.count >= 4, segments[2] == "gallery" {
            return .gallery(did: did, rkey: segments[3])
        }

        if segments.count >= 4, segments[2] == "story" {
            return .story(did: did, rkey: segments[3])
        }

        return .profile(did: did)
    }

    var galleryUri: String? {
        if case let .gallery(did, rkey) = self {
            return "at://\(did)/social.grain.gallery/\(rkey)"
        }
        return nil
    }
}

extension DeepLink {
    /// The push this link corresponds to, if it is one.
    ///
    /// Stories return `nil`: they present as a full-screen cover rather than
    /// joining the navigation stack, so the screen handling the link presents
    /// them itself.
    var route: Route? {
        switch self {
        case let .profile(did):
            .profile(did: did)
        case let .gallery(did, rkey):
            .gallery(uri: "at://\(did)/social.grain.gallery/\(rkey)")
        case .story:
            nil
        }
    }
}