2026-09-21 11:16:52 +02:00
|
|
|
import Foundation
|
|
|
|
|
|
2026-09-21 10:22:55 +02:00
|
|
|
extension String {
|
|
|
|
|
/// A namespace for the paths of the site's screens.
|
|
|
|
|
///
|
|
|
|
|
/// Screens not built yet are listed too, and answer with the not-found page until they are.
|
|
|
|
|
enum Route {
|
|
|
|
|
/// The account screen.
|
|
|
|
|
static let account = "/account"
|
|
|
|
|
/// The collection tracker.
|
|
|
|
|
static let collection = "/collection"
|
|
|
|
|
/// The events screen.
|
|
|
|
|
static let events = "/events"
|
|
|
|
|
/// The public grading guide.
|
|
|
|
|
static let gradingGuide = "/grading-guide"
|
|
|
|
|
/// The browse / home screen.
|
|
|
|
|
static let home = "/"
|
|
|
|
|
/// The message threads.
|
|
|
|
|
static let messages = "/messages"
|
|
|
|
|
/// The open-a-shop onboarding.
|
|
|
|
|
static let openShop = "/sell/open-a-shop"
|
|
|
|
|
/// The privacy statement.
|
|
|
|
|
static let privacy = "/privacy"
|
|
|
|
|
/// The passkey recovery screen.
|
|
|
|
|
static let recover = "/recover"
|
|
|
|
|
/// The search results screen.
|
|
|
|
|
static let search = "/search"
|
|
|
|
|
/// The seller dashboard.
|
|
|
|
|
static let sellerDashboard = "/sell"
|
|
|
|
|
/// The rules sellers agree to.
|
|
|
|
|
static let sellerRules = "/seller-rules"
|
|
|
|
|
/// The series index.
|
|
|
|
|
static let series = "/series"
|
|
|
|
|
/// The passkey sign-in screen.
|
|
|
|
|
static let signIn = "/sign-in"
|
|
|
|
|
/// The terms of service.
|
|
|
|
|
static let terms = "/terms"
|
|
|
|
|
/// The want list.
|
|
|
|
|
static let wants = "/wants"
|
2026-09-21 11:16:52 +02:00
|
|
|
|
|
|
|
|
/// The path of a listing's detail screen.
|
|
|
|
|
/// - Parameter slug: the listing's URL slug.
|
|
|
|
|
static func listing(
|
|
|
|
|
_ slug: String
|
|
|
|
|
) -> String {
|
|
|
|
|
"/listing/\(slug)"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The path of a shop's public screen.
|
|
|
|
|
/// - Parameter slug: the shop's URL slug.
|
|
|
|
|
static func shop(
|
|
|
|
|
_ slug: String
|
|
|
|
|
) -> String {
|
|
|
|
|
"/shop/\(slug)"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The path of the sign-in screen, returning to the given path afterwards.
|
|
|
|
|
/// - Parameter path: the path the visitor's gated action started from.
|
|
|
|
|
static func signIn(
|
|
|
|
|
returningTo path: String
|
|
|
|
|
) -> String {
|
|
|
|
|
"\(signIn)?return=\(path.addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? "")"
|
|
|
|
|
}
|
2026-09-21 10:22:55 +02:00
|
|
|
}
|
|
|
|
|
}
|
2026-09-21 11:16:52 +02:00
|
|
|
|
|
|
|
|
// MARK: - Constants
|
|
|
|
|
|
|
|
|
|
private extension CharacterSet {
|
|
|
|
|
/// The characters a query value carries unescaped.
|
|
|
|
|
static let urlQueryValueAllowed = CharacterSet.urlQueryAllowed.subtracting(.init(charactersIn: "&=+?#"))
|
|
|
|
|
}
|