Skip to content

Instantly share code, notes, and snippets.

@KenLPham
Last active November 29, 2021 17:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KenLPham/034147d6fc5e53b9166bf9e0b8935d66 to your computer and use it in GitHub Desktop.
Save KenLPham/034147d6fc5e53b9166bf9e0b8935d66 to your computer and use it in GitHub Desktop.
import SwiftUI
import ComposableNavigator
import ComposableDeeplinking
@main
struct WTFSwiftUIApp: App {
let navigator: Navigator
let dataSource: Navigator.Datasource
var linkHandler: DeeplinkHandler {
DeeplinkHandler(navigator: self.navigator, parser: .handler)
}
init () {
self.dataSource = .init(root: AScreen())
self.navigator = Navigator(dataSource: dataSource).debug()
}
var body: some Scene {
WindowGroup {
Root(dataSource: dataSource, navigator: navigator, pathBuilder: AScreen.Builder())
.onOpenURL { url in
guard let deeplink = Deeplink(url: url, matching: "wtf") else { return }
print("Handling:", url)
linkHandler.handle(deeplink: deeplink)
}
}
}
}
// MARK: - Helper
extension View {
@inlinable func redacted (reason: RedactionReasons = .placeholder, active: Bool) -> some View {
self.redacted(reason: reason, active: .constant(active))
}
@inlinable func redacted (reason: RedactionReasons = .placeholder, active: Binding<Bool>) -> some View {
self.modifier(RedactViewModifier(reason: reason, active: active))
}
}
public struct RedactViewModifier: ViewModifier {
@Binding var redact: Bool
let reason: RedactionReasons
public init (reason: RedactionReasons, active: Binding<Bool>) {
self._redact = active
self.reason = reason
}
public func body (content: Content) -> some View {
if self.redact {
content.redacted(reason: reason)
} else {
content
}
}
}
// MARK: - Views
struct AView: View {
@Environment(\.navigator) var navigator
@Environment(\.currentScreenID) var screenId
var value: Int?
var loading: Bool {
value == nil
}
var body: some View {
VStack {
Text("Value: \(value ?? 0)")
.redacted(reason: .placeholder, active: loading)
Button("To BView") {
navigator.go(to: BScreen(), on: screenId)
}
}
}
}
struct BView: View {
var body: some View {
Text("Hello World")
}
}
// MARK: - Screens
struct AScreen: Screen {
var presentationStyle: ScreenPresentationStyle = .push
var value: Int?
struct Builder: NavigationTree {
var builder: some PathBuilder {
Screen(
content: { (screen: AScreen) in
AView(value: screen.value)
},
nesting: {
BScreen.Builder()
}
)
}
}
}
struct BScreen: Screen {
var presentationStyle: ScreenPresentationStyle = .push
struct Builder: NavigationTree {
var builder: some PathBuilder {
Screen(
BScreen.self,
content: {
BView()
}
)
}
}
}
// MARK: - Deeplink
extension DeeplinkParser {
// wtf://a?id=20/b
static let handler = DeeplinkParser { link in
guard link.components.count >= 1, link.components[0].name == "a", case let .value(idArg) = link.components[0].arguments?["id"], let id = Int(idArg) else { return nil }
var path = [
AScreen(value: id).eraseToAnyScreen()
]
if link.components.count == 2, link.components[1].name == "b" {
path.append(BScreen().eraseToAnyScreen())
}
return path
}
}
// MARK: TEMP FIX
/*
extension Screen {
static func == (lhs: Self, rhs: Self) -> Bool {
lhs.presentationStyle == rhs.presentationStyle && type(of: lhs) == type(of: rhs)
}
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment