Skip to content

Commit

Permalink
Backport to iOS 14
Browse files Browse the repository at this point in the history
  • Loading branch information
auramagi committed Aug 1, 2023
1 parent dcf770e commit f9865d7
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 54 deletions.
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import PackageDescription

let package = Package(
name: "Destinations",
platforms: [.iOS(.v15), .macOS(.v12), .macCatalyst(.v15), .tvOS(.v15), .watchOS(.v8)],
platforms: [.iOS(.v14), .macOS(.v11), .macCatalyst(.v14), .tvOS(.v14), .watchOS(.v7)],
products: [
.library(
name: "Destinations",
Expand Down
59 changes: 39 additions & 20 deletions Sources/Destinations/Core/DestinationView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Created by Mikhail Apurin on 22.07.2023.
//

import Combine
import OSLog
import SwiftUI

Expand All @@ -23,28 +24,46 @@ public struct DestinationView<Value: Hashable>: View {
public init(value: Value) {
self.value = value
}

public var body: some View {
Group {
if let resolver, let provider = updatedProvider ?? resolver.provider(for: Value.self) {
provider(value)
} else {
#if DEBUG
let valueType = String(reflecting: Value.self)
let _ = log.warning("Unable to resolve destination for value type \(valueType, privacy: .public), showing a placeholder.")
Text("⚠️ \(valueType)")
#else
Text("⚠️")
#endif
}
if #available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) {
resolvedView
.task(id: resolver?.id) {
updatedProvider = resolver?.provider(for: Value.self)
guard let resolver else { return }
let values = resolver.providerUpdates(for: Value.self).eraseToAnyPublisher().values
for await provider in values {
updatedProvider = provider
}
updatedProvider = nil
}
} else {
let publisher = resolver?.providerUpdates(for: Value.self).eraseToAnyPublisher() ?? Empty().eraseToAnyPublisher()

resolvedView
.onAppear {
updatedProvider = resolver?.provider(for: Value.self)
}
.onReceive(publisher) {
updatedProvider = $0
}
.onDisappear {
updatedProvider = nil
}
}
.task(id: resolver?.id) {
guard let resolver else { return }
let values = resolver.providerUpdates(for: Value.self).eraseToAnyPublisher().values
for await provider in values {
updatedProvider = provider
}
updatedProvider = nil
}

@ViewBuilder public var resolvedView: some View {
if let resolver, let provider = updatedProvider ?? resolver.provider(for: Value.self) {
provider(value)
} else {
#if DEBUG
let valueType = String(reflecting: Value.self)
let _ = log.warning("Unable to resolve destination for value type \(valueType, privacy: .public), showing a placeholder.")
Text("⚠️ \(valueType)")
#else
Text("⚠️")
#endif
}
}
}
4 changes: 3 additions & 1 deletion Sources/Destinations/Previews/AdvancedUsage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ struct AdvancedUsage_Navigation_Previews: PreviewProvider {
}
}

@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
#if !os(tvOS) && !os(watchOS)
@available(iOS 16.0, macOS 13.0, watchOS 9.0, *)
struct AdvancedUsage_State_Previews: PreviewProvider {
struct FileSizeLabelDestination: ResolvableDestination {
@State private var fileSize: Result<Int, Error>?
Expand Down Expand Up @@ -126,3 +127,4 @@ struct AdvancedUsage_State_Previews: PreviewProvider {
}
}
}
#endif
5 changes: 2 additions & 3 deletions Sources/Destinations/Previews/BasicUsage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ struct BasicUsage_Closure_Previews: PreviewProvider {
var body: some View {
ChildView()
.destination(for: Int.self) { value in
Text(100 + value, format: .number)
Text("\(100 + value)")
}
}
}
Expand All @@ -28,13 +28,12 @@ struct BasicUsage_Closure_Previews: PreviewProvider {
}
}


struct BasicUsage_Destination_Previews: PreviewProvider {
struct MyDestination: ResolvableDestination {
let base: Int

func body(value: Int) -> some View {
Text(base + value, format: .number)
Text("\(base + value)")
}
}

Expand Down
50 changes: 25 additions & 25 deletions Sources/Destinations/Previews/DynamicUpdates.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

import SwiftUI

@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
#if !os(tvOS)
@available(iOS 16.0, macOS 13.0, watchOS 9.0, *)
struct DynamicUpdates_Persistent_Previews: PreviewProvider {
struct ContentView: View {
var body: some View {
Expand All @@ -24,13 +25,12 @@ struct DynamicUpdates_Persistent_Previews: PreviewProvider {
@State var value = 1

var body: some View {
DestinationView(value: value)
.toolbar {
ToolbarItemGroup(placement: .bottomBar) {
Stepper("Value: \(value)", value: $value)
.padding()
}
}
VStack {
DestinationView(value: value)

Stepper("Value: \(value)", value: $value)
}
.padding()
}
}

Expand All @@ -40,7 +40,7 @@ struct DynamicUpdates_Persistent_Previews: PreviewProvider {
@State private var elapsed = 0

var body: some View {
List {
VStack {
Text("Elapsed: \(elapsed, format: .number)")

Text("Value: \(value, format: .number)")
Expand All @@ -57,23 +57,24 @@ struct DynamicUpdates_Persistent_Previews: PreviewProvider {

static var previews: some View {
ContentView()
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}

@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
@available(iOS 16.0, macOS 13.0, watchOS 9.0, *)
@available(tvOS, unavailable)
struct DynamicUpdates_Conditional_Previews: PreviewProvider {
struct ContentView: View {
@State var base = 1

var body: some View {
NavigationStack {
CounterScreen()
.toolbar {
ToolbarItemGroup(placement: .navigationBarTrailing) {
Stepper("Base: \(base)", value: $base)
.padding()
}
}
VStack {
CounterScreen()

Stepper("Base: \(base)", value: $base)
}
.padding()
}
.destination(CustomViewDestination(base: base))
}
Expand All @@ -83,18 +84,15 @@ struct DynamicUpdates_Conditional_Previews: PreviewProvider {
@State var value = 1

var body: some View {
ZStack {
VStack {
if value < 3 {
Text("Value is less than 3")
} else {
DestinationView(value: value)
}
}
.toolbar {
ToolbarItemGroup(placement: .bottomBar) {
Stepper("Value: \(value)", value: $value)
.padding()
}

Stepper("Value: \(value)", value: $value)
.padding()
}
}
}
Expand All @@ -105,7 +103,7 @@ struct DynamicUpdates_Conditional_Previews: PreviewProvider {
@State var elapsed = 0

func body(value: Int) -> some View {
List {
VStack {
Text("Elapsed: \(elapsed, format: .number)")

Text("Base: \(base, format: .number)")
Expand All @@ -124,5 +122,7 @@ struct DynamicUpdates_Conditional_Previews: PreviewProvider {

static var previews: some View {
ContentView()
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
#endif
11 changes: 7 additions & 4 deletions Sources/Destinations/UI/DestinationNavigationLink.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,30 +57,33 @@ struct DestinationNavigationLink_Previews: PreviewProvider {
static var previews: some View {
navigation {
List {
Section("String") {
Section {
DestinationNavigationLink("Value 1", value: "Value 1")

DestinationNavigationLink(value: "Value 2") {
Text("Value 2")
}
} header: {
Text("String")
}

Section("TestDestination.Value") {
Section {
DestinationNavigationLink("Value 1", value: TestDestination.Value(text: "Value 1"))

DestinationNavigationLink(value: TestDestination.Value(text: "Value 2")) {
Text("Value 2")
}
} header: {
Text("TestDestination.Value")
}
}
.headerProminence(.increased)
}
.destination(TestDestination())
.destination(for: String.self) { Text($0) }
}

@ViewBuilder private static func navigation(@ViewBuilder root: () -> some View) -> some View {
if #available(iOS 16.0, *) {
if #available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *) {
NavigationStack {
root().navigationTitle("NavigationStack")
}
Expand Down

0 comments on commit f9865d7

Please sign in to comment.