From 3b8c07d4b8eb1b0aae6209580b3a6f2f3df8df96 Mon Sep 17 00:00:00 2001 From: noppe Date: Thu, 14 Mar 2024 14:44:31 +0900 Subject: [PATCH] Use visionOS SDK instead iOS SDK. (#24) * Enabled visionOS SDK * In visionOS, use openURL. ref: https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller * .safari * Update README.md * Revert ".safari" This reverts commit 812357e1146a292aeea9e933933af0453bfea46a. * Update trySwift.swift * run openURL * syntax --- App/App.xcodeproj/project.pbxproj | 18 +++--- MyLibrary/Package.swift | 2 +- .../Sources/ScheduleFeature/Detail.swift | 6 ++ .../Sources/ScheduleFeature/Schedule.swift | 5 ++ .../Sources/SponsorFeature/Sponsors.swift | 4 ++ .../trySwiftFeature/Acknowledgements.swift | 6 ++ .../Sources/trySwiftFeature/Profile.swift | 6 ++ .../Sources/trySwiftFeature/trySwift.swift | 55 ++++++++----------- README.md | 2 +- 9 files changed, 64 insertions(+), 40 deletions(-) diff --git a/App/App.xcodeproj/project.pbxproj b/App/App.xcodeproj/project.pbxproj index b7ac44b..e302e21 100644 --- a/App/App.xcodeproj/project.pbxproj +++ b/App/App.xcodeproj/project.pbxproj @@ -15,7 +15,7 @@ D583D7CA2B9B634800B94F73 /* ClipApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D583D7C92B9B634800B94F73 /* ClipApp.swift */; }; D583D7CE2B9B634B00B94F73 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D583D7CD2B9B634B00B94F73 /* Assets.xcassets */; }; D583D7D12B9B634B00B94F73 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D583D7D02B9B634B00B94F73 /* Preview Assets.xcassets */; }; - D583D7D62B9B634B00B94F73 /* Clip.app in Embed App Clips */ = {isa = PBXBuildFile; fileRef = D583D7C72B9B634800B94F73 /* Clip.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + D583D7D62B9B634B00B94F73 /* Clip.app in Embed App Clips */ = {isa = PBXBuildFile; fileRef = D583D7C72B9B634800B94F73 /* Clip.app */; platformFilters = (ios, macos, ); settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; D583D7DC2B9B639900B94F73 /* AppFeature in Frameworks */ = {isa = PBXBuildFile; productRef = D583D7DB2B9B639900B94F73 /* AppFeature */; }; /* End PBXBuildFile section */ @@ -273,6 +273,10 @@ /* Begin PBXTargetDependency section */ D583D7D52B9B634B00B94F73 /* PBXTargetDependency */ = { isa = PBXTargetDependency; + platformFilters = ( + ios, + macos, + ); target = D583D7C62B9B634800B94F73 /* Clip */; targetProxy = D583D7D42B9B634B00B94F73 /* PBXContainerItemProxy */; }; @@ -439,12 +443,12 @@ PRODUCT_BUNDLE_IDENTIFIER = jp.tryswift.tokyo.App; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = auto; - SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; SUPPORTS_MACCATALYST = NO; - SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES; + SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = "1,2,7"; }; name = Debug; }; @@ -484,12 +488,12 @@ PRODUCT_BUNDLE_IDENTIFIER = jp.tryswift.tokyo.App; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = auto; - SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; SUPPORTS_MACCATALYST = NO; - SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES; + SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = "1,2,7"; }; name = Release; }; diff --git a/MyLibrary/Package.swift b/MyLibrary/Package.swift index cdc6619..99eb5da 100644 --- a/MyLibrary/Package.swift +++ b/MyLibrary/Package.swift @@ -5,7 +5,7 @@ import PackageDescription let package = Package( name: "MyLibrary", defaultLocalization: "en", - platforms: [.iOS(.v17), .macOS(.v14), .watchOS(.v10), .tvOS(.v17)], + platforms: [.iOS(.v17), .macOS(.v14), .watchOS(.v10), .tvOS(.v17), .visionOS(.v1)], products: [ .library( name: "AppFeature", diff --git a/MyLibrary/Sources/ScheduleFeature/Detail.swift b/MyLibrary/Sources/ScheduleFeature/Detail.swift index 95ee7c9..a602b09 100644 --- a/MyLibrary/Sources/ScheduleFeature/Detail.swift +++ b/MyLibrary/Sources/ScheduleFeature/Detail.swift @@ -39,6 +39,8 @@ public struct ScheduleDetail { public enum Destination { case safari(Safari) } + + @Dependency(\.openURL) var openURL public init() {} @@ -47,8 +49,12 @@ public struct ScheduleDetail { Reduce { state, action in switch action { case let .view(.snsTapped(url)): + #if os(iOS) || os(macOS) state.destination = .safari(.init(url: url)) return .none + #elseif os(visionOS) + return .run { _ in await openURL(url) } + #endif case .destination: return .none case .binding: diff --git a/MyLibrary/Sources/ScheduleFeature/Schedule.swift b/MyLibrary/Sources/ScheduleFeature/Schedule.swift index cd8d08e..0051cae 100644 --- a/MyLibrary/Sources/ScheduleFeature/Schedule.swift +++ b/MyLibrary/Sources/ScheduleFeature/Schedule.swift @@ -87,8 +87,12 @@ public struct Schedule { return .none case .view(.mapItemTapped): let url = URL(string: String(localized: "Guidance URL", bundle: .module))! + #if os(iOS) || os(macOS) state.destination = .guidance(.init(url: url)) return .none + #elseif os(visionOS) + return .run { _ in await openURL(url) } + #endif case .binding, .path, .destination: return .none } @@ -102,6 +106,7 @@ public struct Schedule { public struct ScheduleView: View { @Bindable public var store: StoreOf + let mapTip: MapTip = .init() public init(store: StoreOf) { diff --git a/MyLibrary/Sources/SponsorFeature/Sponsors.swift b/MyLibrary/Sources/SponsorFeature/Sponsors.swift index 8277789..c18bf99 100644 --- a/MyLibrary/Sources/SponsorFeature/Sponsors.swift +++ b/MyLibrary/Sources/SponsorFeature/Sponsors.swift @@ -44,8 +44,12 @@ public struct SponsorsList { case let .view(.sponsorTapped(sponsor)): guard let url = sponsor.link else { return .none } + #if os(iOS) || os(macOS) state.destination = .safari(.init(url: url)) return .none + #elseif os(visionOS) + return .run { _ in await openURL(url) } + #endif case .binding: return .none case .destination: diff --git a/MyLibrary/Sources/trySwiftFeature/Acknowledgements.swift b/MyLibrary/Sources/trySwiftFeature/Acknowledgements.swift index a0cb90a..308e702 100644 --- a/MyLibrary/Sources/trySwiftFeature/Acknowledgements.swift +++ b/MyLibrary/Sources/trySwiftFeature/Acknowledgements.swift @@ -16,13 +16,19 @@ public struct Acknowledgements { case urlTapped(URL) case safari(PresentationAction) } + + @Dependency(\.openURL) var openURL public var body: some ReducerOf { Reduce { state, action in switch action { case let .urlTapped(url): + #if os(iOS) || os(macOS) state.safari = .init(url: url) return .none + #elseif os(visionOS) + return .run { _ in await openURL(url) } + #endif case .safari: return .none } diff --git a/MyLibrary/Sources/trySwiftFeature/Profile.swift b/MyLibrary/Sources/trySwiftFeature/Profile.swift index 3e3bd02..3581b3f 100644 --- a/MyLibrary/Sources/trySwiftFeature/Profile.swift +++ b/MyLibrary/Sources/trySwiftFeature/Profile.swift @@ -31,6 +31,8 @@ public struct Profile { case safari(Safari) } + @Dependency(\.openURL) var openURL + public init() {} public var body: some ReducerOf { @@ -38,8 +40,12 @@ public struct Profile { Reduce { state, action in switch action { case let .view(.snsTapped(url)): + #if os(iOS) || os(macOS) state.destination = .safari(.init(url: url)) return .none + #elseif os(visionOS) + return .run { _ in await openURL(url) } + #endif case .destination: return .none case .binding: diff --git a/MyLibrary/Sources/trySwiftFeature/trySwift.swift b/MyLibrary/Sources/trySwiftFeature/trySwift.swift index 3304166..ed24440 100644 --- a/MyLibrary/Sources/trySwiftFeature/trySwift.swift +++ b/MyLibrary/Sources/trySwiftFeature/trySwift.swift @@ -38,11 +38,10 @@ public struct TrySwift { @Reducer(state: .equatable) public enum Destination { - case codeOfConduct(Safari) - case privacyPolicy(Safari) - case eventbrite(Safari) - case website(Safari) + case safari(Safari) } + + @Dependency(\.openURL) var openURL public init() {} @@ -55,23 +54,39 @@ public struct TrySwift { return .none case .view(.codeOfConductTapped): let url = URL(string: String(localized: "Code of Conduct URL", bundle: .module))! - state.destination = .codeOfConduct(.init(url: url)) + #if os(iOS) || os(macOS) + state.destination = .safari(.init(url: url)) return .none + #elseif os(visionOS) + return .run { _ in await openURL(url) } + #endif case .view(.privacyPolicyTapped): let url = URL(string: String(localized: "Privacy Policy URL", bundle: .module))! - state.destination = .privacyPolicy(.init(url: url)) + #if os(iOS) || os(macOS) + state.destination = .safari(.init(url: url)) return .none + #elseif os(visionOS) + return .run { _ in await openURL(url) } + #endif case .view(.acknowledgementsTapped): state.path.append(.acknowledgements(.init())) return .none case .view(.eventbriteTapped): let url = URL(string: String(localized: "Eventbrite URL", bundle: .module))! - state.destination = .eventbrite(.init(url: url)) + #if os(iOS) || os(macOS) + state.destination = .safari(.init(url: url)) return .none + #elseif os(visionOS) + return .run { _ in await openURL(url) } + #endif case .view(.websiteTapped): let url = URL(string: String(localized: "Website URL", bundle: .module))! - state.destination = .eventbrite(.init(url: url)) + #if os(iOS) || os(macOS) + state.destination = .safari(.init(url: url)) return .none + #elseif os(visionOS) + return .run { _ in await openURL(url) } + #endif case let .path(.element(_, .organizers(.delegate(.organizerTapped(organizer))))): state.path.append(.profile(.init(organizer: organizer))) return .none @@ -171,32 +186,10 @@ public struct TrySwiftView: View { } .navigationTitle(Text("try! Swift", bundle: .module)) .sheet( - item: $store.scope(state: \.destination?.codeOfConduct, action: \.destination.codeOfConduct) + item: $store.scope(state: \.destination?.safari, action: \.destination.safari) ) { sheetStore in SafariViewRepresentation(url: sheetStore.url) .ignoresSafeArea() - .navigationTitle(Text("Code of Conduct", bundle: .module)) } - .sheet( - item: $store.scope(state: \.destination?.privacyPolicy, action: \.destination.privacyPolicy), - content: { sheetStore in - SafariViewRepresentation(url: sheetStore.url) - .ignoresSafeArea() - .navigationTitle(Text("Privacy Policy", bundle: .module)) - } - ) - .sheet( - item: $store.scope(state: \.destination?.eventbrite, action: \.destination.eventbrite), - content: { sheetStore in - SafariViewRepresentation(url: sheetStore.url) - .ignoresSafeArea() - } - ) - .sheet( - item: $store.scope(state: \.destination?.website, action: \.destination.website), - content: { sheetStore in - SafariViewRepresentation(url: sheetStore.url) - .ignoresSafeArea() - }) } } diff --git a/README.md b/README.md index 580faf4..5f367b2 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ We've submitted the app to the App Store as MVP, and it's currently under review - [ ] macOS support - [ ] watchOS support - [ ] tvOS support -- [x] visionOS support (Designed for iPad) +- [x] visionOS support ## Requirements