diff --git a/.github/workflows/ci-pull-request.yml b/.github/workflows/ci-pull-request.yml index a00579d..d0f81a7 100644 --- a/.github/workflows/ci-pull-request.yml +++ b/.github/workflows/ci-pull-request.yml @@ -34,16 +34,38 @@ jobs: strategy: matrix: destination: + - platform=iOS Simulator,name=iPhone 14 Pro,OS=16.0 + - platform=iOS Simulator,name=iPhone 14 Pro,OS=16.5 + - platform=iOS Simulator,name=iPhone 15 Pro,OS=17.0 - platform=iOS Simulator,name=iPhone 15 Pro,OS=17.5 + - platform=iOS Simulator,name=iPad Pro (12.9-inch) (6th generation),OS=16.0 + - platform=iOS Simulator,name=iPad Pro (12.9-inch) (6th generation),OS=16.5 + - platform=iOS Simulator,name=iPad Pro (12.9-inch) (6th generation),OS=17.0 - platform=iOS Simulator,name=iPad Pro (12.9-inch) (6th generation),OS=17.5 + - platform=tvOS Simulator,name=Apple TV 4K (3rd generation) (at 1080p),OS=17.0 - platform=tvOS Simulator,name=Apple TV 4K (3rd generation) (at 1080p),OS=17.5 - - platform=watchOS Simulator,name=Apple Watch SE (44mm) (2nd generation),OS=10.5 + - platform=macOS,arch=arm64 with: path: AppExample/Example scheme: Example destination: ${{ matrix.destination }} secrets: inherit + build-watchOS-example: + name: Build watchOS Example + needs: build-swiftpm + uses: oversizedev/GithubWorkflows/.github/workflows/build-app.yml@main + strategy: + matrix: + destination: + - platform=watchOS Simulator,name=Apple Watch SE (44mm) (2nd generation),OS=10.0 + - platform=watchOS Simulator,name=Apple Watch SE (44mm) (2nd generation),OS=10.5 + with: + path: AppExample/Example + scheme: Example (watchOS) Watch App + destination: ${{ matrix.destination }} + secrets: inherit + # tests: # name: Test # needs: build-example diff --git a/.github/workflows/ci-push.yml b/.github/workflows/ci-push.yml index cc427ce..21ff79b 100644 --- a/.github/workflows/ci-push.yml +++ b/.github/workflows/ci-push.yml @@ -33,15 +33,37 @@ jobs: strategy: matrix: destination: + - platform=iOS Simulator,name=iPhone 14 Pro,OS=16.0 + - platform=iOS Simulator,name=iPhone 14 Pro,OS=16.5 + - platform=iOS Simulator,name=iPhone 15 Pro,OS=17.0 - platform=iOS Simulator,name=iPhone 15 Pro,OS=17.5 + - platform=iOS Simulator,name=iPad Pro (12.9-inch) (6th generation),OS=16.0 + - platform=iOS Simulator,name=iPad Pro (12.9-inch) (6th generation),OS=16.5 + - platform=iOS Simulator,name=iPad Pro (12.9-inch) (6th generation),OS=17.0 - platform=iOS Simulator,name=iPad Pro (12.9-inch) (6th generation),OS=17.5 + - platform=tvOS Simulator,name=Apple TV 4K (3rd generation) (at 1080p),OS=17.0 - platform=tvOS Simulator,name=Apple TV 4K (3rd generation) (at 1080p),OS=17.5 - - platform=watchOS Simulator,name=Apple Watch SE (44mm) (2nd generation),OS=10.5 + - platform=macOS,arch=arm64 with: path: AppExample/Example scheme: Example destination: ${{ matrix.destination }} secrets: inherit + + build-watchOS-example: + name: Build watchOS Example + needs: build-swiftpm + uses: oversizedev/GithubWorkflows/.github/workflows/build-app.yml@main + strategy: + matrix: + destination: + - platform=watchOS Simulator,name=Apple Watch SE (44mm) (2nd generation),OS=10.0 + - platform=watchOS Simulator,name=Apple Watch SE (44mm) (2nd generation),OS=10.5 + with: + path: AppExample/Example + scheme: Example (watchOS) Watch App + destination: ${{ matrix.destination }} + secrets: inherit # tests: # name: Test @@ -51,7 +73,9 @@ jobs: bump: name: Bump version - needs: build-example + needs: + - build-example + - build-watchOS-example uses: oversizedev/GithubWorkflows/.github/workflows/bump.yml@main secrets: inherit diff --git a/AppExample/Example (watchOS) Watch App/Assets.xcassets/AccentColor.colorset/Contents.json b/AppExample/Example (watchOS) Watch App/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/AppExample/Example (watchOS) Watch App/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AppExample/Example (watchOS) Watch App/Assets.xcassets/AppIcon.appiconset/Contents.json b/AppExample/Example (watchOS) Watch App/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..49c81cd --- /dev/null +++ b/AppExample/Example (watchOS) Watch App/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "watchos", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AppExample/Example (watchOS) Watch App/Assets.xcassets/Contents.json b/AppExample/Example (watchOS) Watch App/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/AppExample/Example (watchOS) Watch App/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AppExample/Example (watchOS) Watch App/ContentView.swift b/AppExample/Example (watchOS) Watch App/ContentView.swift new file mode 100644 index 0000000..9cce011 --- /dev/null +++ b/AppExample/Example (watchOS) Watch App/ContentView.swift @@ -0,0 +1,30 @@ +// +// Copyright © 2024 Alexander Romanov +// ContentView.swift, created on 19.05.2024 +// + +import OversizeKit +import OversizeContactsKit +import OversizeLocationKit +import OversizePhotoKit +import OversizeCalendarKit +import OversizeNoticeKit +import OversizeNotificationKit +import OversizeOnboardingKit +import SwiftUI + +struct ContentView: View { + var body: some View { + VStack { + Image(systemName: "globe") + .imageScale(.large) + .foregroundStyle(.tint) + Text("Hello, world!") + } + .padding() + } +} + +#Preview { + ContentView() +} diff --git a/AppExample/Example (watchOS) Watch App/Example__watchOS_App.swift b/AppExample/Example (watchOS) Watch App/Example__watchOS_App.swift new file mode 100644 index 0000000..fbf5231 --- /dev/null +++ b/AppExample/Example (watchOS) Watch App/Example__watchOS_App.swift @@ -0,0 +1,22 @@ +// +// Copyright © 2024 Alexander Romanov +// Example__watchOS_App.swift, created on 19.05.2024 +// + +import Factory +import OversizeKit +import OversizeServices +import OversizeUI +import SwiftUI + +@main +struct Example__watchOS__Watch_AppApp: App { + + @Injected(\.appStateService) var appStateService: AppStateService + + var body: some Scene { + WindowGroup { + ContentView() + } + } +} diff --git a/AppExample/Example (watchOS) Watch App/Preview Content/Preview Assets.xcassets/Contents.json b/AppExample/Example (watchOS) Watch App/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/AppExample/Example (watchOS) Watch App/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AppExample/Example.xcodeproj/project.pbxproj b/AppExample/Example.xcodeproj/project.pbxproj index a93b920..6c37460 100644 --- a/AppExample/Example.xcodeproj/project.pbxproj +++ b/AppExample/Example.xcodeproj/project.pbxproj @@ -22,19 +22,57 @@ 840CD68E2AC0E39D00C6AAD0 /* ExampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 840CD68D2AC0E39D00C6AAD0 /* ExampleApp.swift */; }; 840CD6902AC0E3A600C6AAD0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 840CD68F2AC0E3A600C6AAD0 /* Assets.xcassets */; }; 840CD6932AC0E3A600C6AAD0 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 840CD6922AC0E3A600C6AAD0 /* Preview Assets.xcassets */; }; - 840CD69E2AC0E43000C6AAD0 /* OversizeCalendarKit in Frameworks */ = {isa = PBXBuildFile; productRef = 840CD69D2AC0E43000C6AAD0 /* OversizeCalendarKit */; }; - 840CD6A02AC0E43000C6AAD0 /* OversizeContactsKit in Frameworks */ = {isa = PBXBuildFile; productRef = 840CD69F2AC0E43000C6AAD0 /* OversizeContactsKit */; }; - 840CD6A22AC0E43000C6AAD0 /* OversizeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 840CD6A12AC0E43000C6AAD0 /* OversizeKit */; }; - 840CD6A42AC0E43000C6AAD0 /* OversizeLocationKit in Frameworks */ = {isa = PBXBuildFile; productRef = 840CD6A32AC0E43000C6AAD0 /* OversizeLocationKit */; }; - 840CD6A62AC0E43000C6AAD0 /* OversizeNoticeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 840CD6A52AC0E43000C6AAD0 /* OversizeNoticeKit */; }; - 840CD6A82AC0E43000C6AAD0 /* OversizeNotificationKit in Frameworks */ = {isa = PBXBuildFile; productRef = 840CD6A72AC0E43000C6AAD0 /* OversizeNotificationKit */; }; - 840CD6AA2AC0E43000C6AAD0 /* OversizeOnboardingKit in Frameworks */ = {isa = PBXBuildFile; productRef = 840CD6A92AC0E43000C6AAD0 /* OversizeOnboardingKit */; }; - 840CD6AC2AC0E43000C6AAD0 /* OversizePhotoKit in Frameworks */ = {isa = PBXBuildFile; productRef = 840CD6AB2AC0E43000C6AAD0 /* OversizePhotoKit */; }; 840CD6AF2AC0E44E00C6AAD0 /* Factory in Frameworks */ = {isa = PBXBuildFile; productRef = 840CD6AE2AC0E44E00C6AAD0 /* Factory */; }; 840CD6B12AC0E6E200C6AAD0 /* Products.storekit in Resources */ = {isa = PBXBuildFile; fileRef = 840CD6B02AC0E6E200C6AAD0 /* Products.storekit */; }; - 845A59332BA4FD2B00988D52 /* OversizeModels in Frameworks */ = {isa = PBXBuildFile; productRef = 845A59322BA4FD2B00988D52 /* OversizeModels */; }; + 84664C312BF9FD6400A24148 /* Example (watchOS) Watch App.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 84664C302BF9FD6400A24148 /* Example (watchOS) Watch App.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 84664C362BF9FD6400A24148 /* Example__watchOS_App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84664C352BF9FD6400A24148 /* Example__watchOS_App.swift */; }; + 84664C382BF9FD6400A24148 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84664C372BF9FD6400A24148 /* ContentView.swift */; }; + 84664C3A2BF9FD6500A24148 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 84664C392BF9FD6500A24148 /* Assets.xcassets */; }; + 84664C3D2BF9FD6500A24148 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 84664C3C2BF9FD6500A24148 /* Preview Assets.xcassets */; }; + 84664C472BF9FDC200A24148 /* Factory in Frameworks */ = {isa = PBXBuildFile; productRef = 84664C462BF9FDC200A24148 /* Factory */; }; + 848479442BF9FF94003FC3FC /* OversizeCalendarKit in Frameworks */ = {isa = PBXBuildFile; productRef = 848479432BF9FF94003FC3FC /* OversizeCalendarKit */; }; + 848479462BF9FF94003FC3FC /* OversizeContactsKit in Frameworks */ = {isa = PBXBuildFile; productRef = 848479452BF9FF94003FC3FC /* OversizeContactsKit */; }; + 848479482BF9FF94003FC3FC /* OversizeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 848479472BF9FF94003FC3FC /* OversizeKit */; }; + 8484794A2BF9FF94003FC3FC /* OversizeLocationKit in Frameworks */ = {isa = PBXBuildFile; productRef = 848479492BF9FF94003FC3FC /* OversizeLocationKit */; }; + 8484794C2BF9FF94003FC3FC /* OversizeNoticeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 8484794B2BF9FF94003FC3FC /* OversizeNoticeKit */; }; + 8484794E2BF9FF94003FC3FC /* OversizeNotificationKit in Frameworks */ = {isa = PBXBuildFile; productRef = 8484794D2BF9FF94003FC3FC /* OversizeNotificationKit */; }; + 848479502BF9FF94003FC3FC /* OversizeOnboardingKit in Frameworks */ = {isa = PBXBuildFile; productRef = 8484794F2BF9FF94003FC3FC /* OversizeOnboardingKit */; }; + 848479522BF9FF94003FC3FC /* OversizePhotoKit in Frameworks */ = {isa = PBXBuildFile; productRef = 848479512BF9FF94003FC3FC /* OversizePhotoKit */; }; + 848479542BF9FFA4003FC3FC /* OversizeCalendarKit in Frameworks */ = {isa = PBXBuildFile; productRef = 848479532BF9FFA4003FC3FC /* OversizeCalendarKit */; }; + 848479562BF9FFA4003FC3FC /* OversizeContactsKit in Frameworks */ = {isa = PBXBuildFile; productRef = 848479552BF9FFA4003FC3FC /* OversizeContactsKit */; }; + 848479582BF9FFA4003FC3FC /* OversizeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 848479572BF9FFA4003FC3FC /* OversizeKit */; }; + 8484795A2BF9FFA4003FC3FC /* OversizeLocationKit in Frameworks */ = {isa = PBXBuildFile; productRef = 848479592BF9FFA4003FC3FC /* OversizeLocationKit */; }; + 8484795C2BF9FFA4003FC3FC /* OversizeNoticeKit in Frameworks */ = {isa = PBXBuildFile; productRef = 8484795B2BF9FFA4003FC3FC /* OversizeNoticeKit */; }; + 8484795E2BF9FFA4003FC3FC /* OversizeNotificationKit in Frameworks */ = {isa = PBXBuildFile; productRef = 8484795D2BF9FFA4003FC3FC /* OversizeNotificationKit */; }; + 848479602BF9FFA4003FC3FC /* OversizeOnboardingKit in Frameworks */ = {isa = PBXBuildFile; productRef = 8484795F2BF9FFA4003FC3FC /* OversizeOnboardingKit */; }; + 848479622BF9FFA4003FC3FC /* OversizePhotoKit in Frameworks */ = {isa = PBXBuildFile; productRef = 848479612BF9FFA4003FC3FC /* OversizePhotoKit */; }; + 848479652BFA0E64003FC3FC /* TestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848479642BFA0E64003FC3FC /* TestView.swift */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 84664C322BF9FD6400A24148 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 840CD6592AC0E39D00C6AAD0 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 84664C2F2BF9FD6400A24148; + remoteInfo = "Example (watchOS) Watch App"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 84664C412BF9FD6500A24148 /* Embed Watch Content */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(CONTENTS_FOLDER_PATH)/Watch"; + dstSubfolderSpec = 16; + files = ( + 84664C312BF9FD6400A24148 /* Example (watchOS) Watch App.app in Embed Watch Content */, + ); + name = "Embed Watch Content"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 840CD6632AC0E39D00C6AAD0 /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 840CD6682AC0E39D00C6AAD0 /* AppSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSettingsView.swift; sourceTree = ""; }; @@ -58,6 +96,15 @@ 840CD6922AC0E3A600C6AAD0 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 840CD6942AC0E3A600C6AAD0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 840CD6B02AC0E6E200C6AAD0 /* Products.storekit */ = {isa = PBXFileReference; lastKnownFileType = text; path = Products.storekit; sourceTree = ""; }; + 84664C2B2BF9FD6400A24148 /* Example (watchOS).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Example (watchOS).app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 84664C302BF9FD6400A24148 /* Example (watchOS) Watch App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Example (watchOS) Watch App.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 84664C352BF9FD6400A24148 /* Example__watchOS_App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Example__watchOS_App.swift; sourceTree = ""; }; + 84664C372BF9FD6400A24148 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + 84664C392BF9FD6500A24148 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 84664C3C2BF9FD6500A24148 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 848479642BFA0E64003FC3FC /* TestView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestView.swift; sourceTree = ""; }; + 84DE88812BF9FEED00CCF37A /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Package.swift; path = ../Package.swift; sourceTree = ""; }; + 84DE88822BF9FF5100CCF37A /* OversizeKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = OversizeKit; path = ..; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -65,16 +112,31 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 840CD6AC2AC0E43000C6AAD0 /* OversizePhotoKit in Frameworks */, + 848479622BF9FFA4003FC3FC /* OversizePhotoKit in Frameworks */, + 848479542BF9FFA4003FC3FC /* OversizeCalendarKit in Frameworks */, + 8484795E2BF9FFA4003FC3FC /* OversizeNotificationKit in Frameworks */, 840CD6AF2AC0E44E00C6AAD0 /* Factory in Frameworks */, - 840CD69E2AC0E43000C6AAD0 /* OversizeCalendarKit in Frameworks */, - 840CD6A82AC0E43000C6AAD0 /* OversizeNotificationKit in Frameworks */, - 840CD6A22AC0E43000C6AAD0 /* OversizeKit in Frameworks */, - 840CD6A42AC0E43000C6AAD0 /* OversizeLocationKit in Frameworks */, - 840CD6A62AC0E43000C6AAD0 /* OversizeNoticeKit in Frameworks */, - 845A59332BA4FD2B00988D52 /* OversizeModels in Frameworks */, - 840CD6A02AC0E43000C6AAD0 /* OversizeContactsKit in Frameworks */, - 840CD6AA2AC0E43000C6AAD0 /* OversizeOnboardingKit in Frameworks */, + 848479582BF9FFA4003FC3FC /* OversizeKit in Frameworks */, + 8484795A2BF9FFA4003FC3FC /* OversizeLocationKit in Frameworks */, + 8484795C2BF9FFA4003FC3FC /* OversizeNoticeKit in Frameworks */, + 848479562BF9FFA4003FC3FC /* OversizeContactsKit in Frameworks */, + 848479602BF9FFA4003FC3FC /* OversizeOnboardingKit in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84664C2D2BF9FD6400A24148 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 848479522BF9FF94003FC3FC /* OversizePhotoKit in Frameworks */, + 848479442BF9FF94003FC3FC /* OversizeCalendarKit in Frameworks */, + 8484794E2BF9FF94003FC3FC /* OversizeNotificationKit in Frameworks */, + 84664C472BF9FDC200A24148 /* Factory in Frameworks */, + 848479482BF9FF94003FC3FC /* OversizeKit in Frameworks */, + 8484794A2BF9FF94003FC3FC /* OversizeLocationKit in Frameworks */, + 8484794C2BF9FF94003FC3FC /* OversizeNoticeKit in Frameworks */, + 848479462BF9FF94003FC3FC /* OversizeContactsKit in Frameworks */, + 848479502BF9FF94003FC3FC /* OversizeOnboardingKit in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -84,8 +146,11 @@ 840CD6582AC0E39D00C6AAD0 = { isa = PBXGroup; children = ( + 84DE88822BF9FF5100CCF37A /* OversizeKit */, 840CD6652AC0E39D00C6AAD0 /* Example */, + 84664C342BF9FD6400A24148 /* Example (watchOS) Watch App */, 840CD6642AC0E39D00C6AAD0 /* Products */, + 84664C452BF9FDC200A24148 /* Frameworks */, ); sourceTree = ""; }; @@ -93,6 +158,8 @@ isa = PBXGroup; children = ( 840CD6632AC0E39D00C6AAD0 /* Example.app */, + 84664C2B2BF9FD6400A24148 /* Example (watchOS).app */, + 84664C302BF9FD6400A24148 /* Example (watchOS) Watch App.app */, ); name = Products; sourceTree = ""; @@ -101,6 +168,7 @@ isa = PBXGroup; children = ( 840CD68D2AC0E39D00C6AAD0 /* ExampleApp.swift */, + 848479632BFA0E55003FC3FC /* Test */, 840CD6662AC0E39D00C6AAD0 /* Screens */, 840CD6782AC0E39D00C6AAD0 /* Router */, 840CD67D2AC0E39D00C6AAD0 /* Resources */, @@ -189,6 +257,41 @@ path = "Preview Content"; sourceTree = ""; }; + 84664C342BF9FD6400A24148 /* Example (watchOS) Watch App */ = { + isa = PBXGroup; + children = ( + 84664C352BF9FD6400A24148 /* Example__watchOS_App.swift */, + 84664C372BF9FD6400A24148 /* ContentView.swift */, + 84664C392BF9FD6500A24148 /* Assets.xcassets */, + 84664C3B2BF9FD6500A24148 /* Preview Content */, + ); + path = "Example (watchOS) Watch App"; + sourceTree = ""; + }; + 84664C3B2BF9FD6500A24148 /* Preview Content */ = { + isa = PBXGroup; + children = ( + 84664C3C2BF9FD6500A24148 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + 84664C452BF9FDC200A24148 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 84DE88812BF9FEED00CCF37A /* Package.swift */, + ); + name = Frameworks; + sourceTree = ""; + }; + 848479632BFA0E55003FC3FC /* Test */ = { + isa = PBXGroup; + children = ( + 848479642BFA0E64003FC3FC /* TestView.swift */, + ); + path = Test; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -206,21 +309,65 @@ ); name = Example; packageProductDependencies = ( - 840CD69D2AC0E43000C6AAD0 /* OversizeCalendarKit */, - 840CD69F2AC0E43000C6AAD0 /* OversizeContactsKit */, - 840CD6A12AC0E43000C6AAD0 /* OversizeKit */, - 840CD6A32AC0E43000C6AAD0 /* OversizeLocationKit */, - 840CD6A52AC0E43000C6AAD0 /* OversizeNoticeKit */, - 840CD6A72AC0E43000C6AAD0 /* OversizeNotificationKit */, - 840CD6A92AC0E43000C6AAD0 /* OversizeOnboardingKit */, - 840CD6AB2AC0E43000C6AAD0 /* OversizePhotoKit */, 840CD6AE2AC0E44E00C6AAD0 /* Factory */, - 845A59322BA4FD2B00988D52 /* OversizeModels */, + 848479532BF9FFA4003FC3FC /* OversizeCalendarKit */, + 848479552BF9FFA4003FC3FC /* OversizeContactsKit */, + 848479572BF9FFA4003FC3FC /* OversizeKit */, + 848479592BF9FFA4003FC3FC /* OversizeLocationKit */, + 8484795B2BF9FFA4003FC3FC /* OversizeNoticeKit */, + 8484795D2BF9FFA4003FC3FC /* OversizeNotificationKit */, + 8484795F2BF9FFA4003FC3FC /* OversizeOnboardingKit */, + 848479612BF9FFA4003FC3FC /* OversizePhotoKit */, ); productName = Example; productReference = 840CD6632AC0E39D00C6AAD0 /* Example.app */; productType = "com.apple.product-type.application"; }; + 84664C2A2BF9FD6400A24148 /* Example (watchOS) */ = { + isa = PBXNativeTarget; + buildConfigurationList = 84664C422BF9FD6500A24148 /* Build configuration list for PBXNativeTarget "Example (watchOS)" */; + buildPhases = ( + 84664C292BF9FD6400A24148 /* Resources */, + 84664C412BF9FD6500A24148 /* Embed Watch Content */, + ); + buildRules = ( + ); + dependencies = ( + 84664C332BF9FD6400A24148 /* PBXTargetDependency */, + ); + name = "Example (watchOS)"; + productName = "Example (watchOS)"; + productReference = 84664C2B2BF9FD6400A24148 /* Example (watchOS).app */; + productType = "com.apple.product-type.application.watchapp2-container"; + }; + 84664C2F2BF9FD6400A24148 /* Example (watchOS) Watch App */ = { + isa = PBXNativeTarget; + buildConfigurationList = 84664C3E2BF9FD6500A24148 /* Build configuration list for PBXNativeTarget "Example (watchOS) Watch App" */; + buildPhases = ( + 84664C2C2BF9FD6400A24148 /* Sources */, + 84664C2D2BF9FD6400A24148 /* Frameworks */, + 84664C2E2BF9FD6400A24148 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Example (watchOS) Watch App"; + packageProductDependencies = ( + 84664C462BF9FDC200A24148 /* Factory */, + 848479432BF9FF94003FC3FC /* OversizeCalendarKit */, + 848479452BF9FF94003FC3FC /* OversizeContactsKit */, + 848479472BF9FF94003FC3FC /* OversizeKit */, + 848479492BF9FF94003FC3FC /* OversizeLocationKit */, + 8484794B2BF9FF94003FC3FC /* OversizeNoticeKit */, + 8484794D2BF9FF94003FC3FC /* OversizeNotificationKit */, + 8484794F2BF9FF94003FC3FC /* OversizeOnboardingKit */, + 848479512BF9FF94003FC3FC /* OversizePhotoKit */, + ); + productName = "Example (watchOS) Watch App"; + productReference = 84664C302BF9FD6400A24148 /* Example (watchOS) Watch App.app */; + productType = "com.apple.product-type.application"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -228,12 +375,18 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 1500; + LastSwiftUpdateCheck = 1540; LastUpgradeCheck = 1500; TargetAttributes = { 840CD6622AC0E39D00C6AAD0 = { CreatedOnToolsVersion = 15.0; }; + 84664C2A2BF9FD6400A24148 = { + CreatedOnToolsVersion = 15.4; + }; + 84664C2F2BF9FD6400A24148 = { + CreatedOnToolsVersion = 15.4; + }; }; }; buildConfigurationList = 840CD65C2AC0E39D00C6AAD0 /* Build configuration list for PBXProject "Example" */; @@ -255,6 +408,8 @@ projectRoot = ""; targets = ( 840CD6622AC0E39D00C6AAD0 /* Example */, + 84664C2A2BF9FD6400A24148 /* Example (watchOS) */, + 84664C2F2BF9FD6400A24148 /* Example (watchOS) Watch App */, ); }; /* End PBXProject section */ @@ -271,6 +426,22 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 84664C292BF9FD6400A24148 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 84664C2E2BF9FD6400A24148 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 84664C3D2BF9FD6500A24148 /* Preview Assets.xcassets in Resources */, + 84664C3A2BF9FD6500A24148 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -289,12 +460,30 @@ 840CD66D2AC0E39D00C6AAD0 /* AppSettingsPageView.swift in Sources */, 840CD67C2AC0E39D00C6AAD0 /* Screens.swift in Sources */, 840CD6722AC0E39D00C6AAD0 /* OnboardingView.swift in Sources */, + 848479652BFA0E64003FC3FC /* TestView.swift in Sources */, 840CD66B2AC0E39D00C6AAD0 /* AppSettingsViewModel.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; + 84664C2C2BF9FD6400A24148 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 84664C382BF9FD6400A24148 /* ContentView.swift in Sources */, + 84664C362BF9FD6400A24148 /* Example__watchOS_App.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + 84664C332BF9FD6400A24148 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 84664C2F2BF9FD6400A24148 /* Example (watchOS) Watch App */; + targetProxy = 84664C322BF9FD6400A24148 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin XCBuildConfiguration section */ 840CD6952AC0E3A600C6AAD0 /* Debug */ = { isa = XCBuildConfiguration; @@ -487,6 +676,96 @@ }; name = Release; }; + 84664C3F2BF9FD6500A24148 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"Example (watchOS) Watch App/Preview Content\""; + DEVELOPMENT_TEAM = ER582ZK85C; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_CFBundleDisplayName = "Example (watchOS)"; + INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; + INFOPLIST_KEY_WKWatchOnly = YES; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "app.oversize.Example--watchOS-.watchkitapp"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 10.0; + }; + name = Debug; + }; + 84664C402BF9FD6500A24148 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"Example (watchOS) Watch App/Preview Content\""; + DEVELOPMENT_TEAM = ER582ZK85C; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_CFBundleDisplayName = "Example (watchOS)"; + INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; + INFOPLIST_KEY_WKWatchOnly = YES; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "app.oversize.Example--watchOS-.watchkitapp"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 10.0; + }; + name = Release; + }; + 84664C432BF9FD6500A24148 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ER582ZK85C; + INFOPLIST_KEY_CFBundleDisplayName = "Example (watchOS)"; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "app.oversize.Example--watchOS-"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 84664C442BF9FD6500A24148 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ER582ZK85C; + INFOPLIST_KEY_CFBundleDisplayName = "Example (watchOS)"; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "app.oversize.Example--watchOS-"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -508,6 +787,24 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 84664C3E2BF9FD6500A24148 /* Build configuration list for PBXNativeTarget "Example (watchOS) Watch App" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 84664C3F2BF9FD6500A24148 /* Debug */, + 84664C402BF9FD6500A24148 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 84664C422BF9FD6500A24148 /* Build configuration list for PBXNativeTarget "Example (watchOS)" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 84664C432BF9FD6500A24148 /* Debug */, + 84664C442BF9FD6500A24148 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ /* Begin XCLocalSwiftPackageReference section */ @@ -537,47 +834,79 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - 840CD69D2AC0E43000C6AAD0 /* OversizeCalendarKit */ = { + 840CD6AE2AC0E44E00C6AAD0 /* Factory */ = { + isa = XCSwiftPackageProductDependency; + package = 840CD6AD2AC0E44E00C6AAD0 /* XCRemoteSwiftPackageReference "Factory" */; + productName = Factory; + }; + 84664C462BF9FDC200A24148 /* Factory */ = { + isa = XCSwiftPackageProductDependency; + package = 840CD6AD2AC0E44E00C6AAD0 /* XCRemoteSwiftPackageReference "Factory" */; + productName = Factory; + }; + 848479432BF9FF94003FC3FC /* OversizeCalendarKit */ = { isa = XCSwiftPackageProductDependency; productName = OversizeCalendarKit; }; - 840CD69F2AC0E43000C6AAD0 /* OversizeContactsKit */ = { + 848479452BF9FF94003FC3FC /* OversizeContactsKit */ = { isa = XCSwiftPackageProductDependency; productName = OversizeContactsKit; }; - 840CD6A12AC0E43000C6AAD0 /* OversizeKit */ = { + 848479472BF9FF94003FC3FC /* OversizeKit */ = { isa = XCSwiftPackageProductDependency; productName = OversizeKit; }; - 840CD6A32AC0E43000C6AAD0 /* OversizeLocationKit */ = { + 848479492BF9FF94003FC3FC /* OversizeLocationKit */ = { isa = XCSwiftPackageProductDependency; productName = OversizeLocationKit; }; - 840CD6A52AC0E43000C6AAD0 /* OversizeNoticeKit */ = { + 8484794B2BF9FF94003FC3FC /* OversizeNoticeKit */ = { isa = XCSwiftPackageProductDependency; productName = OversizeNoticeKit; }; - 840CD6A72AC0E43000C6AAD0 /* OversizeNotificationKit */ = { + 8484794D2BF9FF94003FC3FC /* OversizeNotificationKit */ = { isa = XCSwiftPackageProductDependency; productName = OversizeNotificationKit; }; - 840CD6A92AC0E43000C6AAD0 /* OversizeOnboardingKit */ = { + 8484794F2BF9FF94003FC3FC /* OversizeOnboardingKit */ = { isa = XCSwiftPackageProductDependency; productName = OversizeOnboardingKit; }; - 840CD6AB2AC0E43000C6AAD0 /* OversizePhotoKit */ = { + 848479512BF9FF94003FC3FC /* OversizePhotoKit */ = { isa = XCSwiftPackageProductDependency; productName = OversizePhotoKit; }; - 840CD6AE2AC0E44E00C6AAD0 /* Factory */ = { + 848479532BF9FFA4003FC3FC /* OversizeCalendarKit */ = { isa = XCSwiftPackageProductDependency; - package = 840CD6AD2AC0E44E00C6AAD0 /* XCRemoteSwiftPackageReference "Factory" */; - productName = Factory; + productName = OversizeCalendarKit; + }; + 848479552BF9FFA4003FC3FC /* OversizeContactsKit */ = { + isa = XCSwiftPackageProductDependency; + productName = OversizeContactsKit; + }; + 848479572BF9FFA4003FC3FC /* OversizeKit */ = { + isa = XCSwiftPackageProductDependency; + productName = OversizeKit; + }; + 848479592BF9FFA4003FC3FC /* OversizeLocationKit */ = { + isa = XCSwiftPackageProductDependency; + productName = OversizeLocationKit; + }; + 8484795B2BF9FFA4003FC3FC /* OversizeNoticeKit */ = { + isa = XCSwiftPackageProductDependency; + productName = OversizeNoticeKit; }; - 845A59322BA4FD2B00988D52 /* OversizeModels */ = { + 8484795D2BF9FFA4003FC3FC /* OversizeNotificationKit */ = { isa = XCSwiftPackageProductDependency; - package = 845A59312BA4FD2B00988D52 /* XCRemoteSwiftPackageReference "OversizeModels" */; - productName = OversizeModels; + productName = OversizeNotificationKit; + }; + 8484795F2BF9FFA4003FC3FC /* OversizeOnboardingKit */ = { + isa = XCSwiftPackageProductDependency; + productName = OversizeOnboardingKit; + }; + 848479612BF9FFA4003FC3FC /* OversizePhotoKit */ = { + isa = XCSwiftPackageProductDependency; + productName = OversizePhotoKit; }; /* End XCSwiftPackageProductDependency section */ }; diff --git a/AppExample/Example.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad/UserInterfaceState.xcuserstate b/AppExample/Example.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad/UserInterfaceState.xcuserstate index 106aac6..cacb16d 100644 Binary files a/AppExample/Example.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad/UserInterfaceState.xcuserstate and b/AppExample/Example.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/AppExample/Example.xcodeproj/xcshareddata/xcschemes/Example (watchOS) Watch App.xcscheme b/AppExample/Example.xcodeproj/xcshareddata/xcschemes/Example (watchOS) Watch App.xcscheme new file mode 100644 index 0000000..06a4734 --- /dev/null +++ b/AppExample/Example.xcodeproj/xcshareddata/xcschemes/Example (watchOS) Watch App.xcscheme @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AppExample/Example.xcodeproj/xcuserdata/admin.xcuserdatad/xcschemes/xcschememanagement.plist b/AppExample/Example.xcodeproj/xcuserdata/admin.xcuserdatad/xcschemes/xcschememanagement.plist index 268deb9..747e56b 100644 --- a/AppExample/Example.xcodeproj/xcuserdata/admin.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/AppExample/Example.xcodeproj/xcuserdata/admin.xcuserdatad/xcschemes/xcschememanagement.plist @@ -4,6 +4,11 @@ SchemeUserState + Example (watchOS) Watch App.xcscheme_^#shared#^_ + + orderHint + 1 + Example.xcscheme_^#shared#^_ orderHint @@ -17,6 +22,16 @@ primary + 84664C2A2BF9FD6400A24148 + + primary + + + 84664C2F2BF9FD6400A24148 + + primary + + diff --git a/AppExample/Example/Screens/Onboarding/OnboardingView.swift b/AppExample/Example/Screens/Onboarding/OnboardingView.swift index c3b89b6..ab5152a 100644 --- a/AppExample/Example/Screens/Onboarding/OnboardingView.swift +++ b/AppExample/Example/Screens/Onboarding/OnboardingView.swift @@ -3,6 +3,8 @@ // OnboardingView.swift, created on 25.09.2023 // + + import Factory import OversizeServices import OversizeUI diff --git a/AppExample/Example/Test/TestView.swift b/AppExample/Example/Test/TestView.swift new file mode 100644 index 0000000..979fd84 --- /dev/null +++ b/AppExample/Example/Test/TestView.swift @@ -0,0 +1,24 @@ +// +// Copyright © 2024 Alexander Romanov +// TestView.swift, created on 19.05.2024 +// + +import OversizeKit +import OversizeContactsKit +import OversizeLocationKit +import OversizePhotoKit +import OversizeCalendarKit +import OversizeNoticeKit +import OversizeNotificationKit +import OversizeOnboardingKit +import SwiftUI + +struct TestView: View { + var body: some View { + Text("Hello, World!") + } +} + +#Preview { + TestView() +} diff --git a/Sources/OversizeCalendarKit/CreateEventScreen/CreateEventView.swift b/Sources/OversizeCalendarKit/CreateEventScreen/CreateEventView.swift index 99352cc..d75db38 100644 --- a/Sources/OversizeCalendarKit/CreateEventScreen/CreateEventView.swift +++ b/Sources/OversizeCalendarKit/CreateEventScreen/CreateEventView.swift @@ -102,7 +102,9 @@ import SwiftUI .padding(.bottom, .xxxSmall) .padding(.horizontal, .small) - textEditor + #if !os(watchOS) + textEditor + #endif calendarButtons @@ -142,60 +144,62 @@ import SwiftUI .controlRadius(.large) } - var textEditor: some View { - VStack(spacing: 2) { - TextEditor(text: $viewModel.note) - .onSurfaceHighEmphasisForegroundColor() - .padding(.horizontal, .xSmall) - .padding(.vertical, .xxSmall) - .focused($focusedField, equals: .note) - .body(.medium) - .scrollContentBackground(.hidden) - .background { - #if os(iOS) - RoundedRectangleCorner(radius: 4, corners: [.bottomLeft, .bottomRight]) - .fillSurfaceSecondary() - .overlay(alignment: .topLeading) { - if viewModel.note.isEmpty { - Text("Note") - .body(.medium) - .onSurfaceDisabledForegroundColor() - .padding(.small) + #if !os(watchOS) + var textEditor: some View { + VStack(spacing: 2) { + TextEditor(text: $viewModel.note) + .onSurfaceHighEmphasisForegroundColor() + .padding(.horizontal, .xSmall) + .padding(.vertical, .xxSmall) + .focused($focusedField, equals: .note) + .body(.medium) + .scrollContentBackground(.hidden) + .background { + #if os(iOS) + RoundedRectangleCorner(radius: 4, corners: [.bottomLeft, .bottomRight]) + .fillSurfaceSecondary() + .overlay(alignment: .topLeading) { + if viewModel.note.isEmpty { + Text("Note") + .body(.medium) + .onSurfaceDisabledForegroundColor() + .padding(.small) + } } - } - #else - RoundedRectangle(cornerRadius: .small) - .fillSurfaceSecondary() - .overlay(alignment: .topLeading) { - if viewModel.note.isEmpty { - Text("Note") - .body(.medium) - .onSurfaceDisabledForegroundColor() - .padding(.small) + #else + RoundedRectangle(cornerRadius: .small) + .fillSurfaceSecondary() + .overlay(alignment: .topLeading) { + if viewModel.note.isEmpty { + Text("Note") + .body(.medium) + .onSurfaceDisabledForegroundColor() + .padding(.small) + } } - } - #endif - } - .frame(minHeight: 76) - - TextField("URL", text: $viewModel.url) - .focused($focusedField, equals: .url) - .onSurfaceHighEmphasisForegroundColor() - .body(.medium) - .padding(.horizontal, .small) - .padding(.vertical, 18) - .background { - #if os(iOS) - RoundedRectangleCorner(radius: 4, corners: [.topLeft, .topRight]) - .fillSurfaceSecondary() - #else - RoundedRectangle(cornerRadius: .small) - .fillSurfaceSecondary() - #endif - } + #endif + } + .frame(minHeight: 76) + + TextField("URL", text: $viewModel.url) + .focused($focusedField, equals: .url) + .onSurfaceHighEmphasisForegroundColor() + .body(.medium) + .padding(.horizontal, .small) + .padding(.vertical, 18) + .background { + #if os(iOS) + RoundedRectangleCorner(radius: 4, corners: [.topLeft, .topRight]) + .fillSurfaceSecondary() + #else + RoundedRectangle(cornerRadius: .small) + .fillSurfaceSecondary() + #endif + } + } + .clipShape(RoundedRectangle(cornerRadius: .large, style: .continuous)) } - .clipShape(RoundedRectangle(cornerRadius: .large, style: .continuous)) - } + #endif var repitView: some View { Group { @@ -475,12 +479,14 @@ import SwiftUI .padding(.horizontal, .medium) .padding(.vertical, 20) .onSurfaceMediumEmphasisForegroundColor() - .background(.ultraThinMaterial) - .overlay(alignment: .top) { - Rectangle() - .fill(Color.onSurfaceHighEmphasis.opacity(0.05)) - .frame(height: 1) - } + #if !os(watchOS) + .background(.ultraThinMaterial) + #endif + .overlay(alignment: .top) { + Rectangle() + .fill(Color.onSurfaceHighEmphasis.opacity(0.05)) + .frame(height: 1) + } } @ViewBuilder diff --git a/Sources/OversizeCalendarKit/CreateEventScreen/CreateEventViewSheet.swift b/Sources/OversizeCalendarKit/CreateEventScreen/CreateEventViewSheet.swift index e7096ce..f9fac0f 100644 --- a/Sources/OversizeCalendarKit/CreateEventScreen/CreateEventViewSheet.swift +++ b/Sources/OversizeCalendarKit/CreateEventScreen/CreateEventViewSheet.swift @@ -93,9 +93,13 @@ import SwiftUI CalendarPicker(selection: $viewModel.calendar, calendars: viewModel.calendars, sourses: viewModel.sourses) .presentationDetents([.large]) case .location: - AddressPicker(address: $viewModel.locationName, location: $viewModel.location) - .interactiveDismissDisabled(true) - .presentationDetents([.large]) + #if !os(watchOS) + AddressPicker(address: $viewModel.locationName, location: $viewModel.location) + .interactiveDismissDisabled(true) + .presentationDetents([.large]) + #else + EmptyView() + #endif case .repeat: RepeatPicker(selectionRule: $viewModel.repitRule, selectionEndRule: $viewModel.repitEndRule) diff --git a/Sources/OversizeCalendarKit/Pickers/RepeatPicker.swift b/Sources/OversizeCalendarKit/Pickers/RepeatPicker.swift index 71fd9d4..be20de4 100644 --- a/Sources/OversizeCalendarKit/Pickers/RepeatPicker.swift +++ b/Sources/OversizeCalendarKit/Pickers/RepeatPicker.swift @@ -116,16 +116,20 @@ import SwiftUI .textFieldStyle(DefaultPlaceholderTextFieldStyle()) .focused($isFocusedRepitCount) case .endDate: - DatePicker("Date", selection: Binding(get: { - endDate - }, set: { newDate in - endDate = newDate - endRule = .endDate(newDate) - })) - #if os(iOS) - .datePickerStyle(.wheel) + #if !os(watchOS) + DatePicker("Date", selection: Binding(get: { + endDate + }, set: { newDate in + endDate = newDate + endRule = .endDate(newDate) + })) + #if os(iOS) + .datePickerStyle(.wheel) + #endif + .labelsHidden() + #else + ProgressView() #endif - .labelsHidden() } } } diff --git a/Sources/OversizeContactsKit/AttendeesList/AttendeesView.swift b/Sources/OversizeContactsKit/AttendeesList/AttendeesView.swift index 6af1afd..25d53c8 100644 --- a/Sources/OversizeContactsKit/AttendeesList/AttendeesView.swift +++ b/Sources/OversizeContactsKit/AttendeesList/AttendeesView.swift @@ -91,7 +91,11 @@ import SwiftUI @ViewBuilder private func placeholder() -> some View { - LoaderOverlayView() + #if os(watchOS) + ProgressView() + #else + LoaderOverlayView() + #endif } } #endif diff --git a/Sources/OversizeContactsKit/ContactsPicker/EmailPickerView.swift b/Sources/OversizeContactsKit/ContactsPicker/EmailPickerView.swift index 274212f..c575fcb 100644 --- a/Sources/OversizeContactsKit/ContactsPicker/EmailPickerView.swift +++ b/Sources/OversizeContactsKit/ContactsPicker/EmailPickerView.swift @@ -226,7 +226,11 @@ import SwiftUI @ViewBuilder private func placeholder() -> some View { - LoaderOverlayView() + #if os(watchOS) + ProgressView() + #else + LoaderOverlayView() + #endif } } #endif diff --git a/Sources/OversizeLocationKit/AddressField/AddressField.swift b/Sources/OversizeLocationKit/AddressField/AddressField.swift index 1a8faa4..a126453 100644 --- a/Sources/OversizeLocationKit/AddressField/AddressField.swift +++ b/Sources/OversizeLocationKit/AddressField/AddressField.swift @@ -50,7 +50,9 @@ public struct AddressField: View { public var body: some View { Button { - isShowPicker.toggle() + #if !os(watchOS) + isShowPicker.toggle() + #endif } label: { VStack(alignment: .leading, spacing: .xSmall) { if fieldPlaceholderPosition == .adjacent { @@ -86,9 +88,11 @@ public struct AddressField: View { } .foregroundColor(.onSurfaceHighEmphasis) .buttonStyle(.field) - .sheet(isPresented: $isShowPicker) { - AddressPicker(address: $seletedAddress, location: $seletedLocation, place: $seletedPlace) - } + #if !os(watchOS) + .sheet(isPresented: $isShowPicker) { + AddressPicker(address: $seletedAddress, location: $seletedLocation, place: $seletedPlace) + } + #endif } private var fieldOffset: CGFloat { diff --git a/Sources/OversizeLocationKit/AddressPicker/AddressPicker.swift b/Sources/OversizeLocationKit/AddressPicker/AddressPicker.swift index 33b1775..d4a92a4 100644 --- a/Sources/OversizeLocationKit/AddressPicker/AddressPicker.swift +++ b/Sources/OversizeLocationKit/AddressPicker/AddressPicker.swift @@ -11,225 +11,227 @@ import OversizeLocationService import OversizeUI import SwiftUI -public struct AddressPicker: View { - @Environment(\.dismiss) private var dismiss - @StateObject private var viewModel = AddressPickerViewModel() - @FocusState private var isFocusSearth - - @Binding private var seletedAddress: String? - @Binding private var seletedLocation: CLLocationCoordinate2D? - @Binding private var seletedPlace: LocationAddress? - - public init( - address: Binding = .constant(nil), - location: Binding = .constant(nil), - place: Binding = .constant(nil) - ) { - _seletedAddress = address - _seletedLocation = location - _seletedPlace = place - } - - public var body: some View { - PageView("Location") { - LazyVStack(spacing: .zero) { - if viewModel.appError != nil { - currentLocation - } +#if !os(watchOS) + public struct AddressPicker: View { + @Environment(\.dismiss) private var dismiss + @StateObject private var viewModel = AddressPickerViewModel() + @FocusState private var isFocusSearth + + @Binding private var seletedAddress: String? + @Binding private var seletedLocation: CLLocationCoordinate2D? + @Binding private var seletedPlace: LocationAddress? + + public init( + address: Binding = .constant(nil), + location: Binding = .constant(nil), + place: Binding = .constant(nil) + ) { + _seletedAddress = address + _seletedLocation = location + _seletedPlace = place + } - if viewModel.searchTerm.isEmpty, !viewModel.lastSearchAddresses.isEmpty { - HStack(spacing: .zero) { - Text("Recent") - Spacer() + public var body: some View { + PageView("Location") { + LazyVStack(spacing: .zero) { + if viewModel.appError != nil { + currentLocation } - .title3() - .onSurfaceMediumEmphasisForegroundColor() - .padding(.vertical, .xxSmall) - .paddingContent(.horizontal) - recentResults - } else { - results + if viewModel.searchTerm.isEmpty, !viewModel.lastSearchAddresses.isEmpty { + HStack(spacing: .zero) { + Text("Recent") + Spacer() + } + .title3() + .onSurfaceMediumEmphasisForegroundColor() + .padding(.vertical, .xxSmall) + .paddingContent(.horizontal) + + recentResults + } else { + results + } } } - } - .leadingBar { - BarButton(.close) - } - .topToolbar { - TextField("Search places or addresses", text: $viewModel.searchTerm) - .submitScope(viewModel.searchTerm.count < 2) - .textFieldStyle(DefaultPlaceholderTextFieldStyle()) - .focused($isFocusSearth) - .submitLabel(.done) - .onSubmit { - if viewModel.searchTerm.count > 2 { - viewModel.isSaveFromSearth = true - seletedAddress = viewModel.searchTerm - Task { - let coordinate = try? await viewModel.locationService.fetchCoordinateFromAddress(viewModel.searchTerm) - if let coordinate { - let address = try? await viewModel.locationService.fetchAddressFromLocation(coordinate) - seletedLocation = coordinate - seletedPlace = address - } else { - seletedPlace = nil - seletedLocation = nil + .leadingBar { + BarButton(.close) + } + .topToolbar { + TextField("Search places or addresses", text: $viewModel.searchTerm) + .submitScope(viewModel.searchTerm.count < 2) + .textFieldStyle(DefaultPlaceholderTextFieldStyle()) + .focused($isFocusSearth) + .submitLabel(.done) + .onSubmit { + if viewModel.searchTerm.count > 2 { + viewModel.isSaveFromSearth = true + seletedAddress = viewModel.searchTerm + Task { + let coordinate = try? await viewModel.locationService.fetchCoordinateFromAddress(viewModel.searchTerm) + if let coordinate { + let address = try? await viewModel.locationService.fetchAddressFromLocation(coordinate) + seletedLocation = coordinate + seletedPlace = address + } else { + seletedPlace = nil + seletedLocation = nil + } + viewModel.isSaveFromSearth = false + saveToHistory() + dismiss() } - viewModel.isSaveFromSearth = false - saveToHistory() - dismiss() } } - } - .overlay(alignment: .trailing) { - if viewModel.isSaveFromSearth { - ProgressView() - .padding(.trailing, .xSmall) + .overlay(alignment: .trailing) { + if viewModel.isSaveFromSearth { + ProgressView() + .padding(.trailing, .xSmall) + } } - } - } - // .scrollDismissesKeyboard(.immediately) - .task(priority: .background) { - do { - try await viewModel.updateCurrentPosition() - if viewModel.isSaveCurentPositon { - onSaveCurrntPosition() - } - } catch {} - } - .onAppear { - isFocusSearth = true - } - } - - private var currentLocation: some View { - Row("Current Location") { - if viewModel.isFetchUpdatePositon { - viewModel.isSaveCurentPositon = true - } else { - onSaveCurrntPosition() } - } leading: { - IconDeprecated(.navigation) - .iconOnSurface() + // .scrollDismissesKeyboard(.immediately) + .task(priority: .background) { + do { + try await viewModel.updateCurrentPosition() + if viewModel.isSaveCurentPositon { + onSaveCurrntPosition() + } + } catch {} + } + .onAppear { + isFocusSearth = true + } } - .padding(.bottom, viewModel.searchTerm.isEmpty ? .small : .zero) - .loading(viewModel.isSaveCurentPositon) - } - - private var recentResults: some View { - ForEach(viewModel.lastSearchAddresses.reversed()) { address in - Row(address.address ?? address.place?.address ?? "Latitude: \(address.location?.latitude ?? 0), longitude:longitude \(address.location?.longitude ?? 0)") { - if let latitude = address.location?.latitude, let longitude = address.location?.longitude { - onCompleteSearth(seletedAddress: address.address, seletedLocation: CLLocationCoordinate2D(latitude: latitude, longitude: longitude), seletedPlace: address.place, saveToHistory: false) + private var currentLocation: some View { + Row("Current Location") { + if viewModel.isFetchUpdatePositon { + viewModel.isSaveCurentPositon = true } else { - onCompleteSearth(seletedAddress: address.address, seletedLocation: nil, seletedPlace: address.place, saveToHistory: false) + onSaveCurrntPosition() } } leading: { - IconDeprecated(.mapPin) + IconDeprecated(.navigation) .iconOnSurface() } - .rowClearButton { - if let fooOffset = viewModel.lastSearchAddresses.firstIndex(where: { $0.id == address.id }) { - viewModel.lastSearchAddresses.remove(at: fooOffset) + .padding(.bottom, viewModel.searchTerm.isEmpty ? .small : .zero) + .loading(viewModel.isSaveCurentPositon) + } + + private var recentResults: some View { + ForEach(viewModel.lastSearchAddresses.reversed()) { address in + + Row(address.address ?? address.place?.address ?? "Latitude: \(address.location?.latitude ?? 0), longitude:longitude \(address.location?.longitude ?? 0)") { + if let latitude = address.location?.latitude, let longitude = address.location?.longitude { + onCompleteSearth(seletedAddress: address.address, seletedLocation: CLLocationCoordinate2D(latitude: latitude, longitude: longitude), seletedPlace: address.place, saveToHistory: false) + } else { + onCompleteSearth(seletedAddress: address.address, seletedLocation: nil, seletedPlace: address.place, saveToHistory: false) + } + } leading: { + IconDeprecated(.mapPin) + .iconOnSurface() + } + .rowClearButton { + if let fooOffset = viewModel.lastSearchAddresses.firstIndex(where: { $0.id == address.id }) { + viewModel.lastSearchAddresses.remove(at: fooOffset) + } } } } - } - private var results: some View { - ForEach(viewModel.locationResults, id: \.self) { location in + private var results: some View { + ForEach(viewModel.locationResults, id: \.self) { location in - Row(location.title, subtitle: location.subtitle) { - reverseGeo(location: location) - } leading: { - IconDeprecated(.mapPin) - .iconOnSurface() + Row(location.title, subtitle: location.subtitle) { + reverseGeo(location: location) + } leading: { + IconDeprecated(.mapPin) + .iconOnSurface() + } } } - } - func reverseGeo(location: MKLocalSearchCompletion) { - let searchRequest = MKLocalSearch.Request(completion: location) - let search = MKLocalSearch(request: searchRequest) - var coordinateK: CLLocationCoordinate2D? - search.start { response, error in - if error == nil, let coordinate = response?.mapItems.first?.placemark.coordinate { - coordinateK = coordinate - } + func reverseGeo(location: MKLocalSearchCompletion) { + let searchRequest = MKLocalSearch.Request(completion: location) + let search = MKLocalSearch(request: searchRequest) + var coordinateK: CLLocationCoordinate2D? + search.start { response, error in + if error == nil, let coordinate = response?.mapItems.first?.placemark.coordinate { + coordinateK = coordinate + } - if let c = coordinateK { - let location = CLLocation(latitude: c.latitude, longitude: c.longitude) - CLGeocoder().reverseGeocodeLocation(location) { placemarks, error in + if let c = coordinateK { + let location = CLLocation(latitude: c.latitude, longitude: c.longitude) + CLGeocoder().reverseGeocodeLocation(location) { placemarks, error in - guard let placemark = placemarks?.first else { - let errorString = error?.localizedDescription ?? "Unexpected Error" - print("Unable to reverse geocode, \(errorString)") - return - } + guard let placemark = placemarks?.first else { + let errorString = error?.localizedDescription ?? "Unexpected Error" + print("Unable to reverse geocode, \(errorString)") + return + } - let reversedGeoLocation = LocationAddress(with: placemark) + let reversedGeoLocation = LocationAddress(with: placemark) - let address = "\(reversedGeoLocation.streetName) \(reversedGeoLocation.streetNumber)".capitalizingFirstLetter() - onCompleteSearth(seletedAddress: address, seletedLocation: c, seletedPlace: reversedGeoLocation) + let address = "\(reversedGeoLocation.streetName) \(reversedGeoLocation.streetNumber)".capitalizingFirstLetter() + onCompleteSearth(seletedAddress: address, seletedLocation: c, seletedPlace: reversedGeoLocation) + } } } } - } - func onCompleteSearth(seletedAddress: String?, seletedLocation: CLLocationCoordinate2D?, seletedPlace: LocationAddress?, saveToHistory: Bool = true) { - if let seletedAddress { - self.seletedAddress = seletedAddress - } else { - self.seletedAddress = seletedPlace?.address + func onCompleteSearth(seletedAddress: String?, seletedLocation: CLLocationCoordinate2D?, seletedPlace: LocationAddress?, saveToHistory: Bool = true) { + if let seletedAddress { + self.seletedAddress = seletedAddress + } else { + self.seletedAddress = seletedPlace?.address + } + self.seletedLocation = seletedLocation + self.seletedPlace = seletedPlace + if saveToHistory { + self.saveToHistory() + } + dismiss() } - self.seletedLocation = seletedLocation - self.seletedPlace = seletedPlace - if saveToHistory { - self.saveToHistory() + + private func onSaveCurrntPosition() { + Task { + let address = try? await viewModel.locationService.fetchAddressFromLocation(viewModel.currentLocation) + if let address { + seletedAddress = address.address + seletedPlace = address + } else { + seletedAddress = nil + seletedPlace = nil + } + seletedLocation = viewModel.currentLocation + saveToHistory() + dismiss() + } } - dismiss() - } - private func onSaveCurrntPosition() { - Task { - let address = try? await viewModel.locationService.fetchAddressFromLocation(viewModel.currentLocation) - if let address { - seletedAddress = address.address - seletedPlace = address + func saveToHistory() { + let lastSearth: SearchHistoryAddress + if let seletedLocation { + lastSearth = SearchHistoryAddress( + id: UUID().uuidString, + address: seletedAddress, + location: SearchHistoryLocationCoordinate(coordinate: seletedLocation), + place: seletedPlace + ) } else { - seletedAddress = nil - seletedPlace = nil + lastSearth = SearchHistoryAddress( + id: UUID().uuidString, + address: seletedAddress, + location: nil, + place: seletedPlace + ) } - seletedLocation = viewModel.currentLocation - saveToHistory() - dismiss() + viewModel.lastSearchAddresses.append(lastSearth) } - } - func saveToHistory() { - let lastSearth: SearchHistoryAddress - if let seletedLocation { - lastSearth = SearchHistoryAddress( - id: UUID().uuidString, - address: seletedAddress, - location: SearchHistoryLocationCoordinate(coordinate: seletedLocation), - place: seletedPlace - ) - } else { - lastSearth = SearchHistoryAddress( - id: UUID().uuidString, - address: seletedAddress, - location: nil, - place: seletedPlace - ) + private func onDoneAction() { + dismiss() } - viewModel.lastSearchAddresses.append(lastSearth) - } - - private func onDoneAction() { - dismiss() } -} +#endif diff --git a/Sources/OversizeLocationKit/AddressPicker/AddressPickerViewModel.swift b/Sources/OversizeLocationKit/AddressPicker/AddressPickerViewModel.swift index 92e6fd5..0519299 100644 --- a/Sources/OversizeLocationKit/AddressPicker/AddressPickerViewModel.swift +++ b/Sources/OversizeLocationKit/AddressPicker/AddressPickerViewModel.swift @@ -11,75 +11,77 @@ import OversizeLocationService import OversizeModels import SwiftUI -@MainActor -class AddressPickerViewModel: NSObject, ObservableObject { - @Injected(\.locationService) var locationService: LocationServiceProtocol +#if !os(watchOS) + @MainActor + class AddressPickerViewModel: NSObject, ObservableObject { + @Injected(\.locationService) var locationService: LocationServiceProtocol - @Published var locationResults: [MKLocalSearchCompletion] = .init() - @Published var searchTerm: String = .init() - @AppStorage("AppState.LastSearchAddresses") var lastSearchAddresses: [SearchHistoryAddress] = .init() + @Published var locationResults: [MKLocalSearchCompletion] = .init() + @Published var searchTerm: String = .init() + @AppStorage("AppState.LastSearchAddresses") var lastSearchAddresses: [SearchHistoryAddress] = .init() - @Published var currentLocation: CLLocationCoordinate2D = .init(latitude: 0, longitude: 0) + @Published var currentLocation: CLLocationCoordinate2D = .init(latitude: 0, longitude: 0) - @Published var isFetchUpdatePositon: Bool = .init(false) - @Published var isSaveCurentPositon: Bool = .init(false) - @Published var isSaveFromSearth: Bool = .init(false) + @Published var isFetchUpdatePositon: Bool = .init(false) + @Published var isSaveCurentPositon: Bool = .init(false) + @Published var isSaveFromSearth: Bool = .init(false) - private var cancellables: Set = [] + private var cancellables: Set = [] - private var searchCompleter = MKLocalSearchCompleter() - private var currentPromise: ((Result<[MKLocalSearchCompletion], Error>) -> Void)? + private var searchCompleter = MKLocalSearchCompleter() + private var currentPromise: ((Result<[MKLocalSearchCompletion], Error>) -> Void)? - @State var appError: AppError? + @State var appError: AppError? - override init() { - super.init() - searchCompleter.delegate = self - searchCompleter.resultTypes = MKLocalSearchCompleter.ResultType([.address]) + override init() { + super.init() + searchCompleter.delegate = self + searchCompleter.resultTypes = MKLocalSearchCompleter.ResultType([.address]) - $searchTerm - .debounce(for: .seconds(0.2), scheduler: RunLoop.main) - .removeDuplicates() - .flatMap { currentSearchTerm in - self.searchTermToResults(searchTerm: currentSearchTerm) + $searchTerm + .debounce(for: .seconds(0.2), scheduler: RunLoop.main) + .removeDuplicates() + .flatMap { currentSearchTerm in + self.searchTermToResults(searchTerm: currentSearchTerm) + } + .sink(receiveCompletion: { _ in + // Handle error + }, receiveValue: { results in + self.locationResults = results + }) + .store(in: &cancellables) + } + + func searchTermToResults(searchTerm: String) -> Future<[MKLocalSearchCompletion], Error> { + Future { promise in + self.searchCompleter.queryFragment = searchTerm + self.currentPromise = promise } - .sink(receiveCompletion: { _ in - // Handle error - }, receiveValue: { results in - self.locationResults = results - }) - .store(in: &cancellables) + } } - func searchTermToResults(searchTerm: String) -> Future<[MKLocalSearchCompletion], Error> { - Future { promise in - self.searchCompleter.queryFragment = searchTerm - self.currentPromise = promise + extension AddressPickerViewModel: MKLocalSearchCompleterDelegate { + func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) { + currentPromise?(.success(completer.results)) } - } -} -extension AddressPickerViewModel: MKLocalSearchCompleterDelegate { - func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) { - currentPromise?(.success(completer.results)) + func completer(_: MKLocalSearchCompleter, didFailWithError _: Error) {} } - func completer(_: MKLocalSearchCompleter, didFailWithError _: Error) {} -} - -extension AddressPickerViewModel { - func updateCurrentPosition() async throws { - let status = locationService.permissionsStatus() - switch status { - case .success: - isFetchUpdatePositon = true - let currentPosition = try await locationService.currentLocation() - guard let newLocation = currentPosition else { return } - currentLocation = newLocation - print("📍 Location: \(newLocation.latitude), \(newLocation.longitude)") - isFetchUpdatePositon = false - case let .failure(error): - appError = error + extension AddressPickerViewModel { + func updateCurrentPosition() async throws { + let status = locationService.permissionsStatus() + switch status { + case .success: + isFetchUpdatePositon = true + let currentPosition = try await locationService.currentLocation() + guard let newLocation = currentPosition else { return } + currentLocation = newLocation + print("📍 Location: \(newLocation.latitude), \(newLocation.longitude)") + isFetchUpdatePositon = false + case let .failure(error): + appError = error + } } } -} +#endif diff --git a/Sources/OversizeLocationKit/MapCoordinateView/MapCoordinateView.swift b/Sources/OversizeLocationKit/MapCoordinateView/MapCoordinateView.swift index 4aaecb7..f004927 100644 --- a/Sources/OversizeLocationKit/MapCoordinateView/MapCoordinateView.swift +++ b/Sources/OversizeLocationKit/MapCoordinateView/MapCoordinateView.swift @@ -7,154 +7,156 @@ import MapKit import OversizeUI import SwiftUI -public struct MapCoordinateView: View { - @Environment(\.screenSize) var screenSize - @Environment(\.openURL) var openURL - @StateObject var viewModel: MapCoordinateViewModel +#if !os(watchOS) + public struct MapCoordinateView: View { + @Environment(\.screenSize) var screenSize + @Environment(\.openURL) var openURL + @StateObject var viewModel: MapCoordinateViewModel - public init(_ location: CLLocationCoordinate2D, annotation: String? = nil) { - _viewModel = StateObject(wrappedValue: MapCoordinateViewModel(location: location, annotation: annotation)) - } + public init(_ location: CLLocationCoordinate2D, annotation: String? = nil) { + _viewModel = StateObject(wrappedValue: MapCoordinateViewModel(location: location, annotation: annotation)) + } - public var body: some View { - VStack(spacing: 0) { - if #available(iOS 16.0, *) { - mapView - .ignoresSafeArea() - .safeAreaInset(edge: .top) { - ModalNavigationBar(title: viewModel.annotation ?? "", largeTitle: false, leadingBar: { - BarButton(.back) - }, trailingBar: { - BarButton(.icon(.map, action: { - viewModel.isShowRoutePickerSheet.toggle() - })) - }) - .background(.thickMaterial, ignoresSafeAreaEdges: .top) - } - #if os(iOS) - .toolbar(.hidden, for: .tabBar) - #endif - } else { - mapView - .safeAreaInset(edge: .top) { - ModalNavigationBar(title: viewModel.annotation ?? "", largeTitle: false, leadingBar: { - BarButton(.back) - }, trailingBar: { - BarButton(.icon(.map, action: { - viewModel.isShowRoutePickerSheet.toggle() - })) - }) - } + public var body: some View { + VStack(spacing: 0) { + if #available(iOS 16.0, *) { + mapView + .ignoresSafeArea() + .safeAreaInset(edge: .top) { + ModalNavigationBar(title: viewModel.annotation ?? "", largeTitle: false, leadingBar: { + BarButton(.back) + }, trailingBar: { + BarButton(.icon(.map, action: { + viewModel.isShowRoutePickerSheet.toggle() + })) + }) + .background(.thickMaterial, ignoresSafeAreaEdges: .top) + } + #if os(iOS) + .toolbar(.hidden, for: .tabBar) + #endif + } else { + mapView + .safeAreaInset(edge: .top) { + ModalNavigationBar(title: viewModel.annotation ?? "", largeTitle: false, leadingBar: { + BarButton(.back) + }, trailingBar: { + BarButton(.icon(.map, action: { + viewModel.isShowRoutePickerSheet.toggle() + })) + }) + } + } + } + .sheet(isPresented: $viewModel.isShowRoutePickerSheet) { + routeSheetView + .presentationDetents([.height(260)]) } } - .sheet(isPresented: $viewModel.isShowRoutePickerSheet) { - routeSheetView - .presentationDetents([.height(260)]) - } - } - var mapView: some View { - ZStack(alignment: .trailing) { - Map(coordinateRegion: region, showsUserLocation: true, userTrackingMode: $viewModel.userTrackingMode, annotationItems: viewModel.annotations) { - MapMarker(coordinate: $0.coordinate) + var mapView: some View { + ZStack(alignment: .trailing) { + Map(coordinateRegion: region, showsUserLocation: true, userTrackingMode: $viewModel.userTrackingMode, annotationItems: viewModel.annotations) { + MapMarker(coordinate: $0.coordinate) + } + controlButtons } - controlButtons } - } - private var region: Binding { - Binding { - viewModel.region - } set: { region in - DispatchQueue.main.async { - viewModel.region = region + private var region: Binding { + Binding { + viewModel.region + } set: { region in + DispatchQueue.main.async { + viewModel.region = region + } } } - } - var controlButtons: some View { - VStack { - Spacer() - VStack(spacing: .zero) { - Button { - viewModel.zoomIn() - } label: { - IconDeprecated(.plus) - .onSurfaceMediumEmphasisForegroundColor() - .padding(.xxSmall) - } + var controlButtons: some View { + VStack { + Spacer() + VStack(spacing: .zero) { + Button { + viewModel.zoomIn() + } label: { + IconDeprecated(.plus) + .onSurfaceMediumEmphasisForegroundColor() + .padding(.xxSmall) + } + Button { + viewModel.zoomOut() + } label: { + IconDeprecated(.minus) + .onSurfaceMediumEmphasisForegroundColor() + .padding(.xxSmall) + } + } + .background { + Capsule() + .fillSurfacePrimary() + .shadowElevaton(.z1) + } + Spacer() + } + .overlay(alignment: .bottomTrailing, content: { Button { - viewModel.zoomOut() + viewModel.positionInLocation() + } label: { - IconDeprecated(.minus) + IconDeprecated(.navigation) .onSurfaceMediumEmphasisForegroundColor() .padding(.xxSmall) } - } - .background { - Capsule() - .fillSurfacePrimary() - .shadowElevaton(.z1) - } - Spacer() + .background { + Capsule() + .fillSurfacePrimary() + .shadowElevaton(.z1) + } + }) + .padding(.trailing, 16) + .padding(.bottom, screenSize.safeAreaBottom) } - .overlay(alignment: .bottomTrailing, content: { - Button { - viewModel.positionInLocation() - } label: { - IconDeprecated(.navigation) - .onSurfaceMediumEmphasisForegroundColor() - .padding(.xxSmall) - } - .background { - Capsule() - .fillSurfacePrimary() - .shadowElevaton(.z1) - } - }) - .padding(.trailing, 16) - .padding(.bottom, screenSize.safeAreaBottom) - } - - var routeSheetView: some View { - PageView("Route") { - SectionView { - Row("Apple Maps") { - onTapAppleMaps() - } - Row("Google Maps") { - onTapGoogleMaps() + var routeSheetView: some View { + PageView("Route") { + SectionView { + Row("Apple Maps") { + onTapAppleMaps() + } + Row("Google Maps") { + onTapGoogleMaps() + } } } + .leadingBar(leadingBar: { + BarButton(.close) + }) + .backgroundSecondary() + .disableScrollShadow(true) + .surfaceContentRowMargins() } - .leadingBar(leadingBar: { - BarButton(.close) - }) - .backgroundSecondary() - .disableScrollShadow(true) - .surfaceContentRowMargins() - } - func onTapAppleMaps() { - #if !os(tvOS) - let placemark = MKPlacemark(coordinate: viewModel.location, addressDictionary: nil) - let mapItem = MKMapItem(placemark: placemark) - mapItem.name = viewModel.annotation - mapItem.openInMaps() - viewModel.isShowRoutePickerSheet.toggle() - #endif - } + func onTapAppleMaps() { + #if !os(tvOS) + let placemark = MKPlacemark(coordinate: viewModel.location, addressDictionary: nil) + let mapItem = MKMapItem(placemark: placemark) + mapItem.name = viewModel.annotation + mapItem.openInMaps() + viewModel.isShowRoutePickerSheet.toggle() + #endif + } - func onTapGoogleMaps() { - guard let url = URL(string: "comgooglemaps://?saddr=\(viewModel.location.latitude),\(viewModel.location.longitude)") else { return } - openURL(url) + func onTapGoogleMaps() { + guard let url = URL(string: "comgooglemaps://?saddr=\(viewModel.location.latitude),\(viewModel.location.longitude)") else { return } + openURL(url) + } } -} -struct MapCoordinateView_Previews: PreviewProvider { - static var previews: some View { - MapCoordinateView(.init(latitude: 100, longitude: 100)) + struct MapCoordinateView_Previews: PreviewProvider { + static var previews: some View { + MapCoordinateView(.init(latitude: 100, longitude: 100)) + } } -} +#endif diff --git a/Sources/OversizeNotificationKit/Model/LocalNotificationAlertsTimes.swift b/Sources/OversizeNotificationKit/Model/LocalNotificationAlertsTimes.swift index 79909ad..227a8e9 100644 --- a/Sources/OversizeNotificationKit/Model/LocalNotificationAlertsTimes.swift +++ b/Sources/OversizeNotificationKit/Model/LocalNotificationAlertsTimes.swift @@ -3,9 +3,6 @@ // LocalNotificationAlertsTimes.swift // -#if canImport(EventKit) - import EventKit -#endif import Foundation public enum LocalNotificationTime: CaseIterable, Equatable, Identifiable {