krz/hutch
an ios client for sourcehut
clone: git clone https://gitbay.org/krz/hutch.git
v3.0.0: Hutch/App/DeepLink.swift · raw
1import Foundation
2
3/// Represents a parsed `hutch://` deep link.
4enum DeepLink: Equatable {
5 case home
6 case work
7 /// hutch://git/<owner>/<repo>
8 case repository(owner: String, repo: String)
9 /// hutch://todo/<owner>/<tracker>/<ticketId>
10 case ticket(owner: String, tracker: String, ticketId: Int)
11 /// hutch://builds/<jobId>
12 case build(jobId: Int)
13 /// hutch://builds (tab-level)
14 case buildsTab
15 /// hutch://repositories (tab-level)
16 case repositoriesTab
17 /// hutch://trackers (tab-level)
18 case trackersTab
19 /// hutch://status
20 case systemStatus
21 /// hutch://lookup
22 case lookup
23
24 /// Attempt to parse a URL into a DeepLink.
25 /// Expected format: hutch://<path>
26 init?(url: URL) {
27 guard url.scheme == "hutch" else { return nil }
28
29 // url.host gives the first path component for opaque URLs;
30 // use standardized path components from the full string.
31 let components = url.pathComponents(fromScheme: "hutch")
32
33 switch components.first {
34 case "home", nil:
35 self = .home
36
37 case "work", "inbox":
38 self = .work
39
40 case "git" where components.count >= 3:
41 let owner = components[1]
42 let repo = components[2]
43 self = .repository(owner: owner, repo: repo)
44
45 case "todo" where components.count >= 4:
46 let owner = components[1]
47 let tracker = components[2]
48 guard let ticketId = Int(components[3]) else { return nil }
49 self = .ticket(owner: owner, tracker: tracker, ticketId: ticketId)
50
51 case "builds" where components.count >= 2:
52 guard let jobId = Int(components[1]) else { return nil }
53 self = .build(jobId: jobId)
54
55 case "builds":
56 self = .buildsTab
57
58 case "repositories":
59 self = .repositoriesTab
60
61 case "trackers":
62 self = .trackersTab
63
64 case "status":
65 self = .systemStatus
66
67 case "lookup":
68 self = .lookup
69
70 default:
71 return nil
72 }
73 }
74}
75
76private extension URL {
77 /// Parse path components from a custom-scheme URL.
78 /// For `hutch://git/~user/repo`, returns `["git", "~user", "repo"]`.
79 func pathComponents(fromScheme scheme: String) -> [String] {
80 // Remove scheme prefix and split by "/"
81 var str = absoluteString
82 if str.hasPrefix("\(scheme)://") {
83 str = String(str.dropFirst("\(scheme)://".count))
84 }
85 return str.split(separator: "/").map(String.init)
86 }
87}