From 2df8d9909ede47832f11cb6ab90c22aaa5963c7a Mon Sep 17 00:00:00 2001 From: PiotrFLEURY Date: Fri, 4 Mar 2022 09:49:43 +0100 Subject: [PATCH] feat(appleWatch): implement puzzle on appleWatch with communication bridge between Flutter and native --- .gitignore | 5 +- ios/Podfile.lock | 8 +- ios/Runner.xcodeproj/project.pbxproj | 800 +++++++++++++++++- ios/Runner/AppDelegate.swift | 89 +- .../Circular.imageset/Contents.json | 25 + .../Contents.json | 53 ++ .../Extra Large.imageset/Contents.json | 25 + .../Graphic Bezel.imageset/Contents.json | 20 + .../Graphic Circular.imageset/Contents.json | 20 + .../Graphic Corner.imageset/Contents.json | 20 + .../Contents.json | 25 + .../Contents.json | 20 + .../Modular.imageset/Contents.json | 25 + .../Utilitarian.imageset/Contents.json | 25 + .../Assets.xcassets/Contents.json | 6 + .../ComplicationController.swift | 59 ++ .../ContentView.swift | 88 ++ ios/puzzlewatch WatchKit Extension/Info.plist | 16 + .../NotificationController.swift | 33 + .../NotificationView.swift | 20 + .../Preview Assets.xcassets/Contents.json | 6 + .../PushNotificationPayload.apns | 20 + .../RunnerApp.swift | 21 + .../TileView.swift | 40 + .../WatchViewModel.swift | 120 +++ .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 109 +++ ios/puzzlewatch/Assets.xcassets/Contents.json | 6 + ios/puzzlewatchTests/puzzlewatchTests.swift | 36 + .../puzzlewatchUITests.swift | 42 + .../puzzlewatchUITestsLaunchTests.swift | 32 + lib/bloc/puzzle_cubit.dart | 58 +- lib/models/puzzle.dart | 30 +- macos/Flutter/GeneratedPluginRegistrant.swift | 2 + macos/Podfile.lock | 87 +- macos/Runner.xcodeproj/project.pbxproj | 18 + 36 files changed, 1986 insertions(+), 34 deletions(-) create mode 100644 ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json create mode 100644 ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Contents.json create mode 100644 ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json create mode 100644 ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json create mode 100644 ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json create mode 100644 ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json create mode 100644 ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Extra Large.imageset/Contents.json create mode 100644 ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json create mode 100644 ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json create mode 100644 ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json create mode 100644 ios/puzzlewatch WatchKit Extension/Assets.xcassets/Contents.json create mode 100644 ios/puzzlewatch WatchKit Extension/ComplicationController.swift create mode 100644 ios/puzzlewatch WatchKit Extension/ContentView.swift create mode 100644 ios/puzzlewatch WatchKit Extension/Info.plist create mode 100644 ios/puzzlewatch WatchKit Extension/NotificationController.swift create mode 100644 ios/puzzlewatch WatchKit Extension/NotificationView.swift create mode 100644 ios/puzzlewatch WatchKit Extension/Preview Content/Preview Assets.xcassets/Contents.json create mode 100644 ios/puzzlewatch WatchKit Extension/PushNotificationPayload.apns create mode 100644 ios/puzzlewatch WatchKit Extension/RunnerApp.swift create mode 100644 ios/puzzlewatch WatchKit Extension/TileView.swift create mode 100644 ios/puzzlewatch WatchKit Extension/WatchViewModel.swift create mode 100644 ios/puzzlewatch/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 ios/puzzlewatch/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ios/puzzlewatch/Assets.xcassets/Contents.json create mode 100644 ios/puzzlewatchTests/puzzlewatchTests.swift create mode 100644 ios/puzzlewatchUITests/puzzlewatchUITests.swift create mode 100644 ios/puzzlewatchUITests/puzzlewatchUITestsLaunchTests.swift diff --git a/.gitignore b/.gitignore index ece7016..9f512cc 100644 --- a/.gitignore +++ b/.gitignore @@ -52,4 +52,7 @@ coverage/ /lib/firebase_options.dart # fvm -.fvm/ \ No newline at end of file +.fvm/ + +# ios +ios/Runner/GoogleService-Info.plist \ No newline at end of file diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 229efa7..acad14d 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -88,6 +88,8 @@ PODS: - SDWebImage/Core (5.12.3) - sensors_plus (0.0.1): - Flutter + - shared_preferences_ios (0.0.1): + - Flutter - SwiftyGif (5.4.3) - volume_controller (0.0.1): - Flutter @@ -102,6 +104,7 @@ DEPENDENCIES: - image_picker (from `.symlinks/plugins/image_picker/ios`) - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`) - sensors_plus (from `.symlinks/plugins/sensors_plus/ios`) + - shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`) - volume_controller (from `.symlinks/plugins/volume_controller/ios`) SPEC REPOS: @@ -138,6 +141,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/path_provider_ios/ios" sensors_plus: :path: ".symlinks/plugins/sensors_plus/ios" + shared_preferences_ios: + :path: ".symlinks/plugins/shared_preferences_ios/ios" volume_controller: :path: ".symlinks/plugins/volume_controller/ios" @@ -166,9 +171,10 @@ SPEC CHECKSUMS: PromisesObjC: 68159ce6952d93e17b2dfe273b8c40907db5ba58 SDWebImage: 53179a2dba77246efa8a9b85f5c5b21f8f43e38f sensors_plus: 5717760720f7e6acd96fdbd75b7428f5ad755ec2 + shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad SwiftyGif: 6c3eafd0ce693cad58bb63d2b2fb9bacb8552780 volume_controller: 531ddf792994285c9b17f9d8a7e4dcdd29b3eae9 -PODFILE CHECKSUM: 4fac2b8711b293a4998a954aca5a13ad96c2f941 +PODFILE CHECKSUM: e11957df1847ff6cf43c5cd436db6afa63bba7da COCOAPODS: 1.11.2 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 8d9fae7..6e06005 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -7,6 +7,22 @@ objects = { /* Begin PBXBuildFile section */ + 104A616927C7848F009F7722 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 104A616827C7848F009F7722 /* GoogleService-Info.plist */; }; + 104A616F27CD28C2009F7722 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 104A616E27CD28C2009F7722 /* Assets.xcassets */; }; + 104A617527CD28C2009F7722 /* puzzlewatch WatchKit Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 104A617427CD28C2009F7722 /* puzzlewatch WatchKit Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 104A617A27CD28C2009F7722 /* RunnerApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 104A617927CD28C2009F7722 /* RunnerApp.swift */; }; + 104A617C27CD28C2009F7722 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 104A617B27CD28C2009F7722 /* ContentView.swift */; }; + 104A617E27CD28C2009F7722 /* NotificationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 104A617D27CD28C2009F7722 /* NotificationController.swift */; }; + 104A618027CD28C2009F7722 /* NotificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 104A617F27CD28C2009F7722 /* NotificationView.swift */; }; + 104A618227CD28C2009F7722 /* ComplicationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 104A618127CD28C2009F7722 /* ComplicationController.swift */; }; + 104A618427CD28C2009F7722 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 104A618327CD28C2009F7722 /* Assets.xcassets */; }; + 104A618727CD28C2009F7722 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 104A618627CD28C2009F7722 /* Preview Assets.xcassets */; }; + 104A619327CD28C2009F7722 /* puzzlewatchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 104A619227CD28C2009F7722 /* puzzlewatchTests.swift */; }; + 104A619D27CD28C2009F7722 /* puzzlewatchUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 104A619C27CD28C2009F7722 /* puzzlewatchUITests.swift */; }; + 104A619F27CD28C2009F7722 /* puzzlewatchUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 104A619E27CD28C2009F7722 /* puzzlewatchUITestsLaunchTests.swift */; }; + 104A61A227CD28C2009F7722 /* puzzlewatch.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 104A616C27CD28C1009F7722 /* puzzlewatch.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 104A61B627CD2906009F7722 /* WatchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 104A61B527CD2906009F7722 /* WatchViewModel.swift */; }; + 104A61B827CD2924009F7722 /* TileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 104A61B727CD2924009F7722 /* TileView.swift */; }; 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 1FDBDE8FE01B48F55FD21DAE /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0498AECB4317D9D7ACB6EADC /* Pods_Runner.framework */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; @@ -16,7 +32,60 @@ 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 104A617627CD28C2009F7722 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 104A617327CD28C2009F7722; + remoteInfo = "puzzlewatch WatchKit Extension"; + }; + 104A618F27CD28C2009F7722 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 104A617327CD28C2009F7722; + remoteInfo = "puzzlewatch WatchKit Extension"; + }; + 104A619927CD28C2009F7722 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 104A616B27CD28C1009F7722; + remoteInfo = puzzlewatch; + }; + 104A61A027CD28C2009F7722 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 104A616B27CD28C1009F7722; + remoteInfo = puzzlewatch; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXCopyFilesBuildPhase section */ + 104A61A327CD28C2009F7722 /* Embed Watch Content */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(CONTENTS_FOLDER_PATH)/Watch"; + dstSubfolderSpec = 16; + files = ( + 104A61A227CD28C2009F7722 /* puzzlewatch.app in Embed Watch Content */, + ); + name = "Embed Watch Content"; + runOnlyForDeploymentPostprocessing = 0; + }; + 104A61A727CD28C2009F7722 /* Embed App Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 104A617527CD28C2009F7722 /* puzzlewatch WatchKit Extension.appex in Embed App Extensions */, + ); + name = "Embed App Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; 9705A1C41CF9048500538489 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -31,6 +100,26 @@ /* Begin PBXFileReference section */ 0498AECB4317D9D7ACB6EADC /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 104A616827C7848F009F7722 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; + 104A616C27CD28C1009F7722 /* puzzlewatch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = puzzlewatch.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 104A616E27CD28C2009F7722 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 104A617427CD28C2009F7722 /* puzzlewatch WatchKit Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "puzzlewatch WatchKit Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; + 104A617927CD28C2009F7722 /* RunnerApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerApp.swift; sourceTree = ""; }; + 104A617B27CD28C2009F7722 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + 104A617D27CD28C2009F7722 /* NotificationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationController.swift; sourceTree = ""; }; + 104A617F27CD28C2009F7722 /* NotificationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationView.swift; sourceTree = ""; }; + 104A618127CD28C2009F7722 /* ComplicationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComplicationController.swift; sourceTree = ""; }; + 104A618327CD28C2009F7722 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 104A618627CD28C2009F7722 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 104A618827CD28C2009F7722 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 104A618927CD28C2009F7722 /* PushNotificationPayload.apns */ = {isa = PBXFileReference; lastKnownFileType = text; path = PushNotificationPayload.apns; sourceTree = ""; }; + 104A618E27CD28C2009F7722 /* puzzlewatchTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = puzzlewatchTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 104A619227CD28C2009F7722 /* puzzlewatchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = puzzlewatchTests.swift; sourceTree = ""; }; + 104A619827CD28C2009F7722 /* puzzlewatchUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = puzzlewatchUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 104A619C27CD28C2009F7722 /* puzzlewatchUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = puzzlewatchUITests.swift; sourceTree = ""; }; + 104A619E27CD28C2009F7722 /* puzzlewatchUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = puzzlewatchUITestsLaunchTests.swift; sourceTree = ""; }; + 104A61B527CD2906009F7722 /* WatchViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchViewModel.swift; sourceTree = ""; }; + 104A61B727CD2924009F7722 /* TileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TileView.swift; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 14AA0355116608B06C6C398F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; @@ -50,6 +139,27 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 104A617127CD28C2009F7722 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 104A618B27CD28C2009F7722 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 104A619527CD28C2009F7722 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EB1CF9000F007C117D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -69,6 +179,57 @@ name = Frameworks; sourceTree = ""; }; + 104A616D27CD28C1009F7722 /* puzzlewatch */ = { + isa = PBXGroup; + children = ( + 104A616E27CD28C2009F7722 /* Assets.xcassets */, + ); + path = puzzlewatch; + sourceTree = ""; + }; + 104A617827CD28C2009F7722 /* puzzlewatch WatchKit Extension */ = { + isa = PBXGroup; + children = ( + 104A617927CD28C2009F7722 /* RunnerApp.swift */, + 104A617B27CD28C2009F7722 /* ContentView.swift */, + 104A617D27CD28C2009F7722 /* NotificationController.swift */, + 104A617F27CD28C2009F7722 /* NotificationView.swift */, + 104A618127CD28C2009F7722 /* ComplicationController.swift */, + 104A618327CD28C2009F7722 /* Assets.xcassets */, + 104A618827CD28C2009F7722 /* Info.plist */, + 104A618927CD28C2009F7722 /* PushNotificationPayload.apns */, + 104A618527CD28C2009F7722 /* Preview Content */, + 104A61B527CD2906009F7722 /* WatchViewModel.swift */, + 104A61B727CD2924009F7722 /* TileView.swift */, + ); + path = "puzzlewatch WatchKit Extension"; + sourceTree = ""; + }; + 104A618527CD28C2009F7722 /* Preview Content */ = { + isa = PBXGroup; + children = ( + 104A618627CD28C2009F7722 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + 104A619127CD28C2009F7722 /* puzzlewatchTests */ = { + isa = PBXGroup; + children = ( + 104A619227CD28C2009F7722 /* puzzlewatchTests.swift */, + ); + path = puzzlewatchTests; + sourceTree = ""; + }; + 104A619B27CD28C2009F7722 /* puzzlewatchUITests */ = { + isa = PBXGroup; + children = ( + 104A619C27CD28C2009F7722 /* puzzlewatchUITests.swift */, + 104A619E27CD28C2009F7722 /* puzzlewatchUITestsLaunchTests.swift */, + ); + path = puzzlewatchUITests; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -85,6 +246,10 @@ children = ( 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, + 104A616D27CD28C1009F7722 /* puzzlewatch */, + 104A617827CD28C2009F7722 /* puzzlewatch WatchKit Extension */, + 104A619127CD28C2009F7722 /* puzzlewatchTests */, + 104A619B27CD28C2009F7722 /* puzzlewatchUITests */, 97C146EF1CF9000F007C117D /* Products */, 9D8FAAC1E732E5DDB91A8610 /* Pods */, 0E6E74F4BCBCF1B816EBE68D /* Frameworks */, @@ -95,6 +260,10 @@ isa = PBXGroup; children = ( 97C146EE1CF9000F007C117D /* Runner.app */, + 104A616C27CD28C1009F7722 /* puzzlewatch.app */, + 104A617427CD28C2009F7722 /* puzzlewatch WatchKit Extension.appex */, + 104A618E27CD28C2009F7722 /* puzzlewatchTests.xctest */, + 104A619827CD28C2009F7722 /* puzzlewatchUITests.xctest */, ); name = Products; sourceTree = ""; @@ -102,6 +271,7 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( + 104A616827C7848F009F7722 /* GoogleService-Info.plist */, 97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, @@ -127,6 +297,76 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + 104A616B27CD28C1009F7722 /* puzzlewatch */ = { + isa = PBXNativeTarget; + buildConfigurationList = 104A61B227CD28C2009F7722 /* Build configuration list for PBXNativeTarget "puzzlewatch" */; + buildPhases = ( + 104A616A27CD28C1009F7722 /* Resources */, + 104A61A727CD28C2009F7722 /* Embed App Extensions */, + ); + buildRules = ( + ); + dependencies = ( + 104A617727CD28C2009F7722 /* PBXTargetDependency */, + ); + name = puzzlewatch; + productName = puzzlewatch; + productReference = 104A616C27CD28C1009F7722 /* puzzlewatch.app */; + productType = "com.apple.product-type.application.watchapp2"; + }; + 104A617327CD28C2009F7722 /* puzzlewatch WatchKit Extension */ = { + isa = PBXNativeTarget; + buildConfigurationList = 104A61B127CD28C2009F7722 /* Build configuration list for PBXNativeTarget "puzzlewatch WatchKit Extension" */; + buildPhases = ( + 104A617027CD28C2009F7722 /* Sources */, + 104A617127CD28C2009F7722 /* Frameworks */, + 104A617227CD28C2009F7722 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "puzzlewatch WatchKit Extension"; + productName = "puzzlewatch WatchKit Extension"; + productReference = 104A617427CD28C2009F7722 /* puzzlewatch WatchKit Extension.appex */; + productType = "com.apple.product-type.watchkit2-extension"; + }; + 104A618D27CD28C2009F7722 /* puzzlewatchTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 104A61B327CD28C2009F7722 /* Build configuration list for PBXNativeTarget "puzzlewatchTests" */; + buildPhases = ( + 104A618A27CD28C2009F7722 /* Sources */, + 104A618B27CD28C2009F7722 /* Frameworks */, + 104A618C27CD28C2009F7722 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 104A619027CD28C2009F7722 /* PBXTargetDependency */, + ); + name = puzzlewatchTests; + productName = puzzlewatchTests; + productReference = 104A618E27CD28C2009F7722 /* puzzlewatchTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 104A619727CD28C2009F7722 /* puzzlewatchUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 104A61B427CD28C2009F7722 /* Build configuration list for PBXNativeTarget "puzzlewatchUITests" */; + buildPhases = ( + 104A619427CD28C2009F7722 /* Sources */, + 104A619527CD28C2009F7722 /* Frameworks */, + 104A619627CD28C2009F7722 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 104A619A27CD28C2009F7722 /* PBXTargetDependency */, + ); + name = puzzlewatchUITests; + productName = puzzlewatchUITests; + productReference = 104A619827CD28C2009F7722 /* puzzlewatchUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; 97C146ED1CF9000F007C117D /* Runner */ = { isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; @@ -140,10 +380,12 @@ 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 598646561EA4E65976AF0527 /* [CP] Embed Pods Frameworks */, 82EB98427F2611F929EBDAF0 /* [CP] Copy Pods Resources */, + 104A61A327CD28C2009F7722 /* Embed Watch Content */, ); buildRules = ( ); dependencies = ( + 104A61A127CD28C2009F7722 /* PBXTargetDependency */, ); name = Runner; productName = Runner; @@ -156,9 +398,24 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftUpdateCheck = 1320; LastUpgradeCheck = 1300; ORGANIZATIONNAME = ""; TargetAttributes = { + 104A616B27CD28C1009F7722 = { + CreatedOnToolsVersion = 13.2.1; + }; + 104A617327CD28C2009F7722 = { + CreatedOnToolsVersion = 13.2.1; + }; + 104A618D27CD28C2009F7722 = { + CreatedOnToolsVersion = 13.2.1; + TestTargetID = 104A617327CD28C2009F7722; + }; + 104A619727CD28C2009F7722 = { + CreatedOnToolsVersion = 13.2.1; + TestTargetID = 104A616B27CD28C1009F7722; + }; 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; LastSwiftMigration = 1100; @@ -179,17 +436,53 @@ projectRoot = ""; targets = ( 97C146ED1CF9000F007C117D /* Runner */, + 104A616B27CD28C1009F7722 /* puzzlewatch */, + 104A617327CD28C2009F7722 /* puzzlewatch WatchKit Extension */, + 104A618D27CD28C2009F7722 /* puzzlewatchTests */, + 104A619727CD28C2009F7722 /* puzzlewatchUITests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 104A616A27CD28C1009F7722 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 104A616F27CD28C2009F7722 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 104A617227CD28C2009F7722 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 104A618727CD28C2009F7722 /* Preview Assets.xcassets in Resources */, + 104A618427CD28C2009F7722 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 104A618C27CD28C2009F7722 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 104A619627CD28C2009F7722 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EC1CF9000F007C117D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 104A616927C7848F009F7722 /* GoogleService-Info.plist in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, ); @@ -285,6 +578,37 @@ /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 104A617027CD28C2009F7722 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 104A617E27CD28C2009F7722 /* NotificationController.swift in Sources */, + 104A61B827CD2924009F7722 /* TileView.swift in Sources */, + 104A617C27CD28C2009F7722 /* ContentView.swift in Sources */, + 104A61B627CD2906009F7722 /* WatchViewModel.swift in Sources */, + 104A618227CD28C2009F7722 /* ComplicationController.swift in Sources */, + 104A617A27CD28C2009F7722 /* RunnerApp.swift in Sources */, + 104A618027CD28C2009F7722 /* NotificationView.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 104A618A27CD28C2009F7722 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 104A619327CD28C2009F7722 /* puzzlewatchTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 104A619427CD28C2009F7722 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 104A619F27CD28C2009F7722 /* puzzlewatchUITestsLaunchTests.swift in Sources */, + 104A619D27CD28C2009F7722 /* puzzlewatchUITests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EA1CF9000F007C117D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -296,6 +620,29 @@ }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + 104A617727CD28C2009F7722 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 104A617327CD28C2009F7722 /* puzzlewatch WatchKit Extension */; + targetProxy = 104A617627CD28C2009F7722 /* PBXContainerItemProxy */; + }; + 104A619027CD28C2009F7722 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 104A617327CD28C2009F7722 /* puzzlewatch WatchKit Extension */; + targetProxy = 104A618F27CD28C2009F7722 /* PBXContainerItemProxy */; + }; + 104A619A27CD28C2009F7722 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 104A616B27CD28C1009F7722 /* puzzlewatch */; + targetProxy = 104A619927CD28C2009F7722 /* PBXContainerItemProxy */; + }; + 104A61A127CD28C2009F7722 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 104A616B27CD28C1009F7722 /* puzzlewatch */; + targetProxy = 104A61A027CD28C2009F7722 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin PBXVariantGroup section */ 97C146FA1CF9000F007C117D /* Main.storyboard */ = { isa = PBXVariantGroup; @@ -316,9 +663,409 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ + 104A61A427CD28C2009F7722 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = H5ZMR627PF; + GCC_C_LANGUAGE_STANDARD = gnu11; + GENERATE_INFOPLIST_FILE = YES; + IBSC_MODULE = puzzlewatch_WatchKit_Extension; + INFOPLIST_KEY_CFBundleDisplayName = puzzlewatch; + INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; + INFOPLIST_KEY_WKCompanionAppBundleIdentifier = fr.xpeho.puzzle; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = fr.xpeho.puzzle.watchkitapp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 8.3; + }; + name = Debug; + }; + 104A61A527CD28C2009F7722 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = H5ZMR627PF; + GCC_C_LANGUAGE_STANDARD = gnu11; + GENERATE_INFOPLIST_FILE = YES; + IBSC_MODULE = puzzlewatch_WatchKit_Extension; + INFOPLIST_KEY_CFBundleDisplayName = puzzlewatch; + INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; + INFOPLIST_KEY_WKCompanionAppBundleIdentifier = fr.xpeho.puzzle; + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = fr.xpeho.puzzle.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 = 8.3; + }; + name = Release; + }; + 104A61A627CD28C2009F7722 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = H5ZMR627PF; + GCC_C_LANGUAGE_STANDARD = gnu11; + GENERATE_INFOPLIST_FILE = YES; + IBSC_MODULE = puzzlewatch_WatchKit_Extension; + INFOPLIST_KEY_CFBundleDisplayName = puzzlewatch; + INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; + INFOPLIST_KEY_WKCompanionAppBundleIdentifier = fr.xpeho.puzzle; + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = fr.xpeho.puzzle.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 = 8.3; + }; + name = Profile; + }; + 104A61A827CD28C2009F7722 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"puzzlewatch WatchKit Extension/Preview Content\""; + DEVELOPMENT_TEAM = H5ZMR627PF; + ENABLE_PREVIEWS = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = "puzzlewatch WatchKit Extension/Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "puzzlewatch WatchKit Extension"; + INFOPLIST_KEY_CLKComplicationPrincipalClass = "$(PRODUCT_MODULE_NAME).ComplicationController"; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = fr.xpeho.puzzle.watchkitapp.watchkitextension; + PRODUCT_NAME = "${TARGET_NAME}"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 8.3; + }; + name = Debug; + }; + 104A61A927CD28C2009F7722 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"puzzlewatch WatchKit Extension/Preview Content\""; + DEVELOPMENT_TEAM = H5ZMR627PF; + ENABLE_PREVIEWS = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = "puzzlewatch WatchKit Extension/Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "puzzlewatch WatchKit Extension"; + INFOPLIST_KEY_CLKComplicationPrincipalClass = "$(PRODUCT_MODULE_NAME).ComplicationController"; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = fr.xpeho.puzzle.watchkitapp.watchkitextension; + 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 = 8.3; + }; + name = Release; + }; + 104A61AA27CD28C2009F7722 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"puzzlewatch WatchKit Extension/Preview Content\""; + DEVELOPMENT_TEAM = H5ZMR627PF; + ENABLE_PREVIEWS = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = "puzzlewatch WatchKit Extension/Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "puzzlewatch WatchKit Extension"; + INFOPLIST_KEY_CLKComplicationPrincipalClass = "$(PRODUCT_MODULE_NAME).ComplicationController"; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = fr.xpeho.puzzle.watchkitapp.watchkitextension; + 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 = 8.3; + }; + name = Profile; + }; + 104A61AB27CD28C2009F7722 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = H5ZMR627PF; + GCC_C_LANGUAGE_STANDARD = gnu11; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = fr.xpeho.puzzle.puzzlewatchTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/puzzlewatch WatchKit Extension.appex/puzzlewatch WatchKit Extension"; + WATCHOS_DEPLOYMENT_TARGET = 8.3; + }; + name = Debug; + }; + 104A61AC27CD28C2009F7722 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = H5ZMR627PF; + GCC_C_LANGUAGE_STANDARD = gnu11; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = fr.xpeho.puzzle.puzzlewatchTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/puzzlewatch WatchKit Extension.appex/puzzlewatch WatchKit Extension"; + WATCHOS_DEPLOYMENT_TARGET = 8.3; + }; + name = Release; + }; + 104A61AD27CD28C2009F7722 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = H5ZMR627PF; + GCC_C_LANGUAGE_STANDARD = gnu11; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = fr.xpeho.puzzle.puzzlewatchTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/puzzlewatch WatchKit Extension.appex/puzzlewatch WatchKit Extension"; + WATCHOS_DEPLOYMENT_TARGET = 8.3; + }; + name = Profile; + }; + 104A61AE27CD28C2009F7722 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = H5ZMR627PF; + GCC_C_LANGUAGE_STANDARD = gnu11; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = fr.xpeho.puzzle.puzzlewatchUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + TEST_TARGET_NAME = puzzlewatch; + WATCHOS_DEPLOYMENT_TARGET = 8.3; + }; + name = Debug; + }; + 104A61AF27CD28C2009F7722 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = H5ZMR627PF; + GCC_C_LANGUAGE_STANDARD = gnu11; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = fr.xpeho.puzzle.puzzlewatchUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + TEST_TARGET_NAME = puzzlewatch; + WATCHOS_DEPLOYMENT_TARGET = 8.3; + }; + name = Release; + }; + 104A61B027CD28C2009F7722 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = H5ZMR627PF; + GCC_C_LANGUAGE_STANDARD = gnu11; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = fr.xpeho.puzzle.puzzlewatchUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + TEST_TARGET_NAME = puzzlewatch; + WATCHOS_DEPLOYMENT_TARGET = 8.3; + }; + name = Profile; + }; 249021D3217E4FDB00AE95B9 /* Profile */ = { isa = XCBuildConfiguration; buildSettings = { + ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES; ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; @@ -360,7 +1107,8 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; + SUPPORTS_MACCATALYST = YES; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -373,7 +1121,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 99622Z377A; + DEVELOPMENT_TEAM = H5ZMR627PF; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -447,6 +1195,7 @@ 97C147041CF9000F007C117D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES; ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; @@ -488,7 +1237,8 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; + SUPPORTS_MACCATALYST = YES; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; TARGETED_DEVICE_FAMILY = "1,2"; @@ -503,7 +1253,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 99622Z377A; + DEVELOPMENT_TEAM = H5ZMR627PF; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -527,7 +1277,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 99622Z377A; + DEVELOPMENT_TEAM = H5ZMR627PF; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -546,6 +1296,46 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 104A61B127CD28C2009F7722 /* Build configuration list for PBXNativeTarget "puzzlewatch WatchKit Extension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 104A61A827CD28C2009F7722 /* Debug */, + 104A61A927CD28C2009F7722 /* Release */, + 104A61AA27CD28C2009F7722 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 104A61B227CD28C2009F7722 /* Build configuration list for PBXNativeTarget "puzzlewatch" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 104A61A427CD28C2009F7722 /* Debug */, + 104A61A527CD28C2009F7722 /* Release */, + 104A61A627CD28C2009F7722 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 104A61B327CD28C2009F7722 /* Build configuration list for PBXNativeTarget "puzzlewatchTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 104A61AB27CD28C2009F7722 /* Debug */, + 104A61AC27CD28C2009F7722 /* Release */, + 104A61AD27CD28C2009F7722 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 104A61B427CD28C2009F7722 /* Build configuration list for PBXNativeTarget "puzzlewatchUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 104A61AE27CD28C2009F7722 /* Debug */, + 104A61AF27CD28C2009F7722 /* Release */, + 104A61B027CD28C2009F7722 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index 70693e4..8024dc6 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -1,13 +1,88 @@ import UIKit import Flutter +import WatchConnectivity @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? - ) -> Bool { - GeneratedPluginRegistrant.register(with: self) - return super.application(application, didFinishLaunchingWithOptions: launchOptions) - } + var session: WCSession? + + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + initFlutterChannel() + if WCSession.isSupported() { + session = WCSession.default; + session?.delegate = self; + session?.activate(); + } + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } + + private func initFlutterChannel() { + if let controller = window?.rootViewController as? FlutterViewController { + let channel = FlutterMethodChannel( + name: "fr.xpeho.puzzle", + binaryMessenger: controller.binaryMessenger) + + channel.setMethodCallHandler({ [weak self] ( + call: FlutterMethodCall, + result: @escaping FlutterResult) -> Void in + switch call.method { + case "puzzleToWatch": + guard let watchSession = self?.session, watchSession.isPaired, + watchSession.isReachable, let methodData = call.arguments as? [String: Any], + let method = methodData["method"], let puzzle = methodData["puzzle"] else { + result(false) + return + } + + let watchData: [String: Any] = ["method": method, "puzzle": puzzle] + watchSession.sendMessage(watchData, replyHandler: nil, errorHandler: nil) + result(true) + case "movesToWatch": + guard let watchSession = self?.session, watchSession.isPaired, + watchSession.isReachable, let methodData = call.arguments as? [String: Any], + let method = methodData["method"], let moves = methodData["moves"] else { + result(false) + return + } + + let watchData: [String: Any] = ["method": method, "moves": moves] + watchSession.sendMessage(watchData, replyHandler: nil, errorHandler: nil) + result(true) + default: + result(FlutterMethodNotImplemented) + } + }) + } + } +} + +@available(iOS 9.3, *) +extension AppDelegate: WCSessionDelegate { + + func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) { + + } + + func sessionDidBecomeInactive(_ session: WCSession) { + + } + + func sessionDidDeactivate(_ session: WCSession) { + + } + + func session(_ session: WCSession, didReceiveMessage message: [String : Any]) { + DispatchQueue.main.async { + if let method = message["method"] as? String, let controller = self.window?.rootViewController as? FlutterViewController { + let channel = FlutterMethodChannel( + name: "fr.xpeho.puzzle", + binaryMessenger: controller.binaryMessenger) + channel.invokeMethod(method, arguments: message["data"]) + } + } + } } diff --git a/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json new file mode 100644 index 0000000..26454ca --- /dev/null +++ b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json @@ -0,0 +1,25 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "auto-scaling" : "auto" + } +} diff --git a/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Contents.json b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Contents.json new file mode 100644 index 0000000..e8b3252 --- /dev/null +++ b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Contents.json @@ -0,0 +1,53 @@ +{ + "assets" : [ + { + "filename" : "Circular.imageset", + "idiom" : "watch", + "role" : "circular" + }, + { + "filename" : "Extra Large.imageset", + "idiom" : "watch", + "role" : "extra-large" + }, + { + "filename" : "Graphic Bezel.imageset", + "idiom" : "watch", + "role" : "graphic-bezel" + }, + { + "filename" : "Graphic Circular.imageset", + "idiom" : "watch", + "role" : "graphic-circular" + }, + { + "filename" : "Graphic Corner.imageset", + "idiom" : "watch", + "role" : "graphic-corner" + }, + { + "filename" : "Graphic Extra Large.imageset", + "idiom" : "watch", + "role" : "graphic-extra-large" + }, + { + "filename" : "Graphic Large Rectangular.imageset", + "idiom" : "watch", + "role" : "graphic-large-rectangular" + }, + { + "filename" : "Modular.imageset", + "idiom" : "watch", + "role" : "modular" + }, + { + "filename" : "Utilitarian.imageset", + "idiom" : "watch", + "role" : "utilitarian" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json new file mode 100644 index 0000000..26454ca --- /dev/null +++ b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json @@ -0,0 +1,25 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "auto-scaling" : "auto" + } +} diff --git a/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json new file mode 100644 index 0000000..6e184db --- /dev/null +++ b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json @@ -0,0 +1,20 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "auto-scaling" : "auto" + } +} diff --git a/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json new file mode 100644 index 0000000..6e184db --- /dev/null +++ b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json @@ -0,0 +1,20 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "auto-scaling" : "auto" + } +} diff --git a/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json new file mode 100644 index 0000000..6e184db --- /dev/null +++ b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json @@ -0,0 +1,20 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "auto-scaling" : "auto" + } +} diff --git a/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Extra Large.imageset/Contents.json b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Extra Large.imageset/Contents.json new file mode 100644 index 0000000..26454ca --- /dev/null +++ b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Extra Large.imageset/Contents.json @@ -0,0 +1,25 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "auto-scaling" : "auto" + } +} diff --git a/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json new file mode 100644 index 0000000..6e184db --- /dev/null +++ b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json @@ -0,0 +1,20 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "auto-scaling" : "auto" + } +} diff --git a/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json new file mode 100644 index 0000000..26454ca --- /dev/null +++ b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json @@ -0,0 +1,25 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "auto-scaling" : "auto" + } +} diff --git a/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json new file mode 100644 index 0000000..26454ca --- /dev/null +++ b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json @@ -0,0 +1,25 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "auto-scaling" : "auto" + } +} diff --git a/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Contents.json b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/ios/puzzlewatch WatchKit Extension/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/puzzlewatch WatchKit Extension/ComplicationController.swift b/ios/puzzlewatch WatchKit Extension/ComplicationController.swift new file mode 100644 index 0000000..f446316 --- /dev/null +++ b/ios/puzzlewatch WatchKit Extension/ComplicationController.swift @@ -0,0 +1,59 @@ +// +// ComplicationController.swift +// puzzlewatch WatchKit Extension +// +// Created by Piotr FLEURY on 28/02/2022. +// + +import ClockKit + + +class ComplicationController: NSObject, CLKComplicationDataSource { + + // MARK: - Complication Configuration + + func getComplicationDescriptors(handler: @escaping ([CLKComplicationDescriptor]) -> Void) { + let descriptors = [ + CLKComplicationDescriptor(identifier: "complication", displayName: "Runner", supportedFamilies: CLKComplicationFamily.allCases) + // Multiple complication support can be added here with more descriptors + ] + + // Call the handler with the currently supported complication descriptors + handler(descriptors) + } + + func handleSharedComplicationDescriptors(_ complicationDescriptors: [CLKComplicationDescriptor]) { + // Do any necessary work to support these newly shared complication descriptors + } + + // MARK: - Timeline Configuration + + func getTimelineEndDate(for complication: CLKComplication, withHandler handler: @escaping (Date?) -> Void) { + // Call the handler with the last entry date you can currently provide or nil if you can't support future timelines + handler(nil) + } + + func getPrivacyBehavior(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationPrivacyBehavior) -> Void) { + // Call the handler with your desired behavior when the device is locked + handler(.showOnLockScreen) + } + + // MARK: - Timeline Population + + func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) { + // Call the handler with the current timeline entry + handler(nil) + } + + func getTimelineEntries(for complication: CLKComplication, after date: Date, limit: Int, withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void) { + // Call the handler with the timeline entries after the given date + handler(nil) + } + + // MARK: - Sample Templates + + func getLocalizableSampleTemplate(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTemplate?) -> Void) { + // This method will be called once per supported complication, and the results will be cached + handler(nil) + } +} diff --git a/ios/puzzlewatch WatchKit Extension/ContentView.swift b/ios/puzzlewatch WatchKit Extension/ContentView.swift new file mode 100644 index 0000000..ddce089 --- /dev/null +++ b/ios/puzzlewatch WatchKit Extension/ContentView.swift @@ -0,0 +1,88 @@ +// +// ContentView.swift +// watch WatchKit Extension +// +// Created by Piotr FLEURY on 20/02/2022. +// + +import SwiftUI +import OSLog + +struct ContentView: View { + @ObservedObject var viewModel: WatchViewModel = WatchViewModel() + @State var scrollAmount = 0.0 + + var crownValueBinding: Binding { + Binding( + get: { self.scrollAmount }, + set: { newValue in + self.scrollAmount = newValue + self.viewModel.shuffle() + } + ) + } + + func valueTapped(value: Int) { + viewModel.swap(value: value) + } + + var body: some View { + ZStack { +// LinearGradient( +// colors: [ +// .gray, +// .green, +// ], startPoint: .top, endPoint: .bottom +// ).edgesIgnoringSafeArea(.all) + ScrollView { + VStack { + HStack { + TileView(value: viewModel.data[0], action: valueTapped) + TileView(value: viewModel.data[1], action: valueTapped) + TileView(value: viewModel.data[2], action: valueTapped) + } + HStack { + TileView(value: viewModel.data[3], action: valueTapped) + TileView(value: viewModel.data[4], action: valueTapped) + TileView(value: viewModel.data[5], action: valueTapped) + } + HStack { + TileView(value: viewModel.data[6], action: valueTapped) + TileView(value: viewModel.data[7], action: valueTapped) + TileView(value: viewModel.data[8], action: valueTapped) + } + Text("Moves: \(viewModel.moves)") + Button(action: { + viewModel.shuffle() + }) { + HStack { + Image(systemName: "shuffle") + Text("Shuffle") + } + } + Button(action: { + viewModel.reset() + }) { + Image(systemName: "arrow.clockwise") + HStack { + Text("Reset") + } + } + } + + + } + .focusable() + .digitalCrownRotation(self.crownValueBinding) + } + + } + + +} + +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + ContentView() + } +} diff --git a/ios/puzzlewatch WatchKit Extension/Info.plist b/ios/puzzlewatch WatchKit Extension/Info.plist new file mode 100644 index 0000000..dd132b1 --- /dev/null +++ b/ios/puzzlewatch WatchKit Extension/Info.plist @@ -0,0 +1,16 @@ + + + + + NSExtension + + NSExtensionAttributes + + WKAppBundleIdentifier + fr.xpeho.puzzle.watchkitapp + + NSExtensionPointIdentifier + com.apple.watchkit + + + diff --git a/ios/puzzlewatch WatchKit Extension/NotificationController.swift b/ios/puzzlewatch WatchKit Extension/NotificationController.swift new file mode 100644 index 0000000..c5eedd1 --- /dev/null +++ b/ios/puzzlewatch WatchKit Extension/NotificationController.swift @@ -0,0 +1,33 @@ +// +// NotificationController.swift +// puzzlewatch WatchKit Extension +// +// Created by Piotr FLEURY on 28/02/2022. +// + +import WatchKit +import SwiftUI +import UserNotifications + +class NotificationController: WKUserNotificationHostingController { + + override var body: NotificationView { + return NotificationView() + } + + override func willActivate() { + // This method is called when watch view controller is about to be visible to user + super.willActivate() + } + + override func didDeactivate() { + // This method is called when watch view controller is no longer visible + super.didDeactivate() + } + + override func didReceive(_ notification: UNNotification) { + // This method is called when a notification needs to be presented. + // Implement it if you use a dynamic notification interface. + // Populate your dynamic notification interface as quickly as possible. + } +} diff --git a/ios/puzzlewatch WatchKit Extension/NotificationView.swift b/ios/puzzlewatch WatchKit Extension/NotificationView.swift new file mode 100644 index 0000000..fec758c --- /dev/null +++ b/ios/puzzlewatch WatchKit Extension/NotificationView.swift @@ -0,0 +1,20 @@ +// +// NotificationView.swift +// puzzlewatch WatchKit Extension +// +// Created by Piotr FLEURY on 28/02/2022. +// + +import SwiftUI + +struct NotificationView: View { + var body: some View { + Text("Hello, World!") + } +} + +struct NotificationView_Previews: PreviewProvider { + static var previews: some View { + NotificationView() + } +} diff --git a/ios/puzzlewatch WatchKit Extension/Preview Content/Preview Assets.xcassets/Contents.json b/ios/puzzlewatch WatchKit Extension/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/ios/puzzlewatch WatchKit Extension/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/puzzlewatch WatchKit Extension/PushNotificationPayload.apns b/ios/puzzlewatch WatchKit Extension/PushNotificationPayload.apns new file mode 100644 index 0000000..c18b00a --- /dev/null +++ b/ios/puzzlewatch WatchKit Extension/PushNotificationPayload.apns @@ -0,0 +1,20 @@ +{ + "aps": { + "alert": { + "body": "Test message", + "title": "Optional title", + "subtitle": "Optional subtitle" + }, + "category": "myCategory", + "thread-id": "5280" + }, + + "WatchKit Simulator Actions": [ + { + "title": "First Button", + "identifier": "firstButtonAction" + } + ], + + "customKey": "Use this file to define a testing payload for your notifications. The aps dictionary specifies the category, alert text and title. The WatchKit Simulator Actions array can provide info for one or more action buttons in addition to the standard Dismiss button. Any other top level keys are custom payload. If you have multiple such JSON files in your project, you'll be able to select them when choosing to debug the notification interface of your Watch App." +} diff --git a/ios/puzzlewatch WatchKit Extension/RunnerApp.swift b/ios/puzzlewatch WatchKit Extension/RunnerApp.swift new file mode 100644 index 0000000..69bd0dc --- /dev/null +++ b/ios/puzzlewatch WatchKit Extension/RunnerApp.swift @@ -0,0 +1,21 @@ +// +// RunnerApp.swift +// puzzlewatch WatchKit Extension +// +// Created by Piotr FLEURY on 28/02/2022. +// + +import SwiftUI + +@main +struct RunnerApp: App { + @SceneBuilder var body: some Scene { + WindowGroup { + NavigationView { + ContentView() + } + } + + WKNotificationScene(controller: NotificationController.self, category: "myCategory") + } +} diff --git a/ios/puzzlewatch WatchKit Extension/TileView.swift b/ios/puzzlewatch WatchKit Extension/TileView.swift new file mode 100644 index 0000000..f59efdc --- /dev/null +++ b/ios/puzzlewatch WatchKit Extension/TileView.swift @@ -0,0 +1,40 @@ +// +// TileView.swift +// watch WatchKit Extension +// +// Created by Piotr FLEURY on 20/02/2022. +// + +import SwiftUI + +struct TileView: View { + let value: Int + let action: (Int) -> Void + + var body: some View { + if(value == 0) { + Text(" ") + .frame(width: 48) + } else { + Button(action: { + action(value) + }) { + Text("\(value)") + } + .frame(width: 48) + .background(Color.green) + .clipShape(RoundedRectangle(cornerRadius: 8.0)) + } + + } +} + +struct TileView_Previews: PreviewProvider { + static var previews: some View { + HStack { + TileView(value: 0, action: {_ in }) + TileView(value: 1, action: {_ in }) + TileView(value: 2, action: {_ in }) + } + } +} diff --git a/ios/puzzlewatch WatchKit Extension/WatchViewModel.swift b/ios/puzzlewatch WatchKit Extension/WatchViewModel.swift new file mode 100644 index 0000000..ebd81bb --- /dev/null +++ b/ios/puzzlewatch WatchKit Extension/WatchViewModel.swift @@ -0,0 +1,120 @@ +// +// WatchViewModel.swift +// watch WatchKit Extension +// +// Created by Piotr FLEURY on 20/02/2022. +// + +import Foundation +import WatchConnectivity +import os + +struct FlutterPuzzle: Encodable, Decodable { + let values: Array + let moves: Int + let complexity: Int +} + +class WatchViewModel: NSObject, ObservableObject { + var session: WCSession + @Published var counter = 0 + @Published var moves = 0 + @Published var data = [1, 2, 3, 4, 5, 6, 7, 8, 0] + + // Add more cases if you have more receive method + enum WatchReceiveMethod: String { + case sendPuzzleToNative + case sendMovesToNative + } + + // Add more cases if you have more sending method + enum WatchSendMethod: String { + case sendPuzzleToFlutter + case sendMovesToFlutter + } + + init(session: WCSession = .default) { + self.session = session + super.init() + self.session.delegate = self + session.activate() + } + + func sendDataMessage(for method: WatchSendMethod, data: String) { + sendMessage(for: method.rawValue, data: data) + } + + func swap(value: Int) { + let valueIndex: Int = data.firstIndex(of: value) ?? 0 + let zeroIndex: Int = data.firstIndex(of: 0) ?? 0 + + data.swapAt(zeroIndex, valueIndex) + moves+=1 + _sendToFlutter() + } + + func shuffle() { + data.shuffle() + moves = 0 + _sendToFlutter() + } + + func reset() { + data = [1, 2, 3, 4, 5, 6, 7, 8, 0] + moves = 0 + _sendToFlutter() + } + + func _sendToFlutter() { + let puzzleValues = self.data.map{String($0)}.joined(separator: ",") + os_log("sending puzzle to Flutter \(puzzleValues)") + sendDataMessage(for: .sendPuzzleToFlutter, data: puzzleValues) + + let moves = self.moves + os_log("sending moves to Flutter \(moves)") + sendDataMessage(for: .sendMovesToFlutter, data: String(moves)) + + } + +} + +extension WatchViewModel: WCSessionDelegate { + + func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) { + + } + + // Receive message From AppDelegate.swift that send from iOS devices + func session(_ session: WCSession, didReceiveMessage message: [String : Any]) { + DispatchQueue.main.async { + guard let method = message["method"] as? String, let enumMethod = WatchReceiveMethod(rawValue: method) else { + return + } + + switch enumMethod { + case .sendMovesToNative: + let movesString = message["moves"] as? String ?? "" + os_log("received moves from flutter \(movesString)") + let moves = Int(movesString) ?? 0 + self.moves = moves + break; + case .sendPuzzleToNative: + let puzzleString = message["puzzle"] as? String ?? "" + os_log("received puzzle from flutter \(puzzleString)") + let puzzleValues = puzzleString.split(separator: ",") + self.data = puzzleValues.map{Int($0) ?? 0} + break; + + } + } + } + + func sendMessage(for method: String, data: String) { + guard session.isReachable else { + return + } + let messageData: [String: Any] = ["method": method, "data": data] + session.sendMessage(messageData, replyHandler: nil, errorHandler: nil) + } + +} diff --git a/ios/puzzlewatch/Assets.xcassets/AccentColor.colorset/Contents.json b/ios/puzzlewatch/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/ios/puzzlewatch/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/puzzlewatch/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/puzzlewatch/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..193150c --- /dev/null +++ b/ios/puzzlewatch/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,109 @@ +{ + "images" : [ + { + "idiom" : "watch", + "role" : "notificationCenter", + "scale" : "2x", + "size" : "24x24", + "subtype" : "38mm" + }, + { + "idiom" : "watch", + "role" : "notificationCenter", + "scale" : "2x", + "size" : "27.5x27.5", + "subtype" : "42mm" + }, + { + "idiom" : "watch", + "role" : "companionSettings", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "watch", + "role" : "companionSettings", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "watch", + "role" : "notificationCenter", + "scale" : "2x", + "size" : "33x33", + "subtype" : "45mm" + }, + { + "idiom" : "watch", + "role" : "appLauncher", + "scale" : "2x", + "size" : "40x40", + "subtype" : "38mm" + }, + { + "idiom" : "watch", + "role" : "appLauncher", + "scale" : "2x", + "size" : "44x44", + "subtype" : "40mm" + }, + { + "idiom" : "watch", + "role" : "appLauncher", + "scale" : "2x", + "size" : "46x46", + "subtype" : "41mm" + }, + { + "idiom" : "watch", + "role" : "appLauncher", + "scale" : "2x", + "size" : "50x50", + "subtype" : "44mm" + }, + { + "idiom" : "watch", + "role" : "appLauncher", + "scale" : "2x", + "size" : "51x51", + "subtype" : "45mm" + }, + { + "idiom" : "watch", + "role" : "quickLook", + "scale" : "2x", + "size" : "86x86", + "subtype" : "38mm" + }, + { + "idiom" : "watch", + "role" : "quickLook", + "scale" : "2x", + "size" : "98x98", + "subtype" : "42mm" + }, + { + "idiom" : "watch", + "role" : "quickLook", + "scale" : "2x", + "size" : "108x108", + "subtype" : "44mm" + }, + { + "idiom" : "watch", + "role" : "quickLook", + "scale" : "2x", + "size" : "117x117", + "subtype" : "45mm" + }, + { + "idiom" : "watch-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/puzzlewatch/Assets.xcassets/Contents.json b/ios/puzzlewatch/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/ios/puzzlewatch/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/puzzlewatchTests/puzzlewatchTests.swift b/ios/puzzlewatchTests/puzzlewatchTests.swift new file mode 100644 index 0000000..f0eaade --- /dev/null +++ b/ios/puzzlewatchTests/puzzlewatchTests.swift @@ -0,0 +1,36 @@ +// +// puzzlewatchTests.swift +// puzzlewatchTests +// +// Created by Piotr FLEURY on 28/02/2022. +// + +import XCTest +@testable import puzzlewatch_WatchKit_Extension + +class puzzlewatchTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/ios/puzzlewatchUITests/puzzlewatchUITests.swift b/ios/puzzlewatchUITests/puzzlewatchUITests.swift new file mode 100644 index 0000000..d3ce9a4 --- /dev/null +++ b/ios/puzzlewatchUITests/puzzlewatchUITests.swift @@ -0,0 +1,42 @@ +// +// puzzlewatchUITests.swift +// puzzlewatchUITests +// +// Created by Piotr FLEURY on 28/02/2022. +// + +import XCTest + +class puzzlewatchUITests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // UI tests must launch the application that they test. + let app = XCUIApplication() + app.launch() + + // Use recording to get started writing UI tests. + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testLaunchPerformance() throws { + if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { + // This measures how long it takes to launch your application. + measure(metrics: [XCTApplicationLaunchMetric()]) { + XCUIApplication().launch() + } + } + } +} diff --git a/ios/puzzlewatchUITests/puzzlewatchUITestsLaunchTests.swift b/ios/puzzlewatchUITests/puzzlewatchUITestsLaunchTests.swift new file mode 100644 index 0000000..5be3bfd --- /dev/null +++ b/ios/puzzlewatchUITests/puzzlewatchUITestsLaunchTests.swift @@ -0,0 +1,32 @@ +// +// puzzlewatchUITestsLaunchTests.swift +// puzzlewatchUITests +// +// Created by Piotr FLEURY on 28/02/2022. +// + +import XCTest + +class puzzlewatchUITestsLaunchTests: XCTestCase { + + override class var runsForEachTargetApplicationUIConfiguration: Bool { + true + } + + override func setUpWithError() throws { + continueAfterFailure = false + } + + func testLaunch() throws { + let app = XCUIApplication() + app.launch() + + // Insert steps here to perform after app launch but before taking a screenshot, + // such as logging into a test account or navigating somewhere in the app + + let attachment = XCTAttachment(screenshot: app.screenshot()) + attachment.name = "Launch Screen" + attachment.lifetime = .keepAlways + add(attachment) + } +} diff --git a/lib/bloc/puzzle_cubit.dart b/lib/bloc/puzzle_cubit.dart index d9c5f82..3fedd9f 100644 --- a/lib/bloc/puzzle_cubit.dart +++ b/lib/bloc/puzzle_cubit.dart @@ -1,6 +1,9 @@ +import 'dart:io'; import 'dart:typed_data'; import 'dart:ui' as ui; +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:get_it/get_it.dart'; import 'package:puzzle/bloc/bloc.dart'; @@ -8,8 +11,40 @@ import 'package:puzzle/models/models.dart'; import 'package:puzzle/services/audio_service.dart'; class PuzzleCubit extends Cubit { - PuzzleCubit() : super(PuzzleState(Puzzle.generate(4)..shuffle())); + PuzzleCubit() : super(PuzzleState(Puzzle.generate(3)..shuffle())) { + channel.setMethodCallHandler((call) async { + debugPrint( + "handling new call from native ${call.method} with arguments ${call.arguments}"); + // Receive data from Native + switch (call.method) { + case "sendMovesToFlutter": + var data = call.arguments as String; + debugPrint("received moves from native: $data"); + emitNewState(state.puzzle, int.parse(data), sendToNative: false); + break; + case "sendPuzzleToFlutter": + var data = call.arguments as String; + debugPrint("received new puzzle state from native $data"); + List values = data.split(","); + debugPrint("values: $values"); + emitNewState( + Puzzle( + complexity: state.puzzle.complexity, + data: values + .map((v) => Puzzle.generateTile( + int.parse(v) - 1, state.puzzle.complexity)) + .toList(), + ), + state.moves, + sendToNative: false); + break; + default: + break; + } + }); + } AudioService audioService = GetIt.I.get(); + final channel = const MethodChannel('fr.xpeho.puzzle'); void shuffle() { emitNewState(state.puzzle.shuffle(), 0); @@ -17,10 +52,12 @@ class PuzzleCubit extends Cubit { /// try to swap the tile with the empty tile trySwap(int value) { - if (state.puzzle.canSwap(value)) { - audioService.play("sounds/Success.mp3", isLocal: true); - } else { - audioService.play("sounds/Error.mp3", isLocal: true); + if (kIsWeb || !Platform.isIOS) { + if (state.puzzle.canSwap(value)) { + audioService.play("sounds/Success.mp3", isLocal: true); + } else { + audioService.play("sounds/Error.mp3", isLocal: true); + } } emitNewState(state.puzzle.trySwap(value), state.moves + 1); } @@ -80,8 +117,17 @@ class PuzzleCubit extends Cubit { emitNewState(Puzzle.generate(state.puzzle.complexity - 1), 0); } - void emitNewState(Puzzle newPuzzle, int moves) { + void emitNewState(Puzzle newPuzzle, int moves, {bool sendToNative = true}) { emit(state.copyWith(puzzle: newPuzzle, moves: moves)); + debugPrint("Sending puzzle to native: ${newPuzzle.values.join(",")}"); + if (sendToNative) { + channel.invokeMethod("puzzleToWatch", { + "method": "sendPuzzleToNative", + "puzzle": newPuzzle.values.join(",") + }); + channel.invokeMethod("movesToWatch", + {"method": "sendMovesToNative", "moves": moves.toString()}); + } } Future loadUiImage(Uint8List? bytes) async { diff --git a/lib/models/puzzle.dart b/lib/models/puzzle.dart index 17489f4..f815163 100644 --- a/lib/models/puzzle.dart +++ b/lib/models/puzzle.dart @@ -15,19 +15,7 @@ class Puzzle { /// Generate value for the puzzle factory Puzzle.generate(int complexity) { final data = List.generate(complexity * complexity, (index) { - var value = index + 1; - if (value == complexity * complexity) { - return Tile( - targetX: complexity - 1, - targetY: complexity - 1, - value: 0, - ); - } - return Tile( - targetX: index % complexity, - targetY: index ~/ complexity, - value: value, - ); + return generateTile(index, complexity); }); return Puzzle( @@ -36,6 +24,22 @@ class Puzzle { ); } + static Tile generateTile(int index, int complexity) { + var value = index + 1; + if (value == complexity * complexity) { + return Tile( + targetX: complexity - 1, + targetY: complexity - 1, + value: 0, + ); + } + return Tile( + targetX: index % complexity, + targetY: index ~/ complexity, + value: value, + ); + } + int getXof(Tile tile) => data.indexOf(tile) % complexity; int getYof(Tile tile) => data.indexOf(tile) ~/ complexity; diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index d51c066..8e96474 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -9,10 +9,12 @@ import audioplayers import cloud_firestore import firebase_core import path_provider_macos +import shared_preferences_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { AudioplayersPlugin.register(with: registry.registrar(forPlugin: "AudioplayersPlugin")) FLTFirebaseFirestorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseFirestorePlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) } diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 6ba65c6..7b769f0 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -1,28 +1,113 @@ PODS: - audioplayers (0.0.1): - FlutterMacOS + - cloud_firestore (3.1.8): + - Firebase/CoreOnly (~> 8.11.0) + - Firebase/Firestore (~> 8.11.0) + - firebase_core + - FlutterMacOS + - Firebase/CoreOnly (8.11.0): + - FirebaseCore (= 8.11.0) + - Firebase/Firestore (8.11.0): + - Firebase/CoreOnly + - FirebaseFirestore (~> 8.11.0) + - firebase_core (1.12.0): + - Firebase/CoreOnly (~> 8.11.0) + - FlutterMacOS + - FirebaseCore (8.11.0): + - FirebaseCoreDiagnostics (~> 8.0) + - GoogleUtilities/Environment (~> 7.7) + - GoogleUtilities/Logger (~> 7.7) + - FirebaseCoreDiagnostics (8.12.0): + - GoogleDataTransport (~> 9.1) + - GoogleUtilities/Environment (~> 7.7) + - GoogleUtilities/Logger (~> 7.7) + - nanopb (~> 2.30908.0) + - FirebaseFirestore (8.11.0): + - FirebaseFirestore/AutodetectLeveldb (= 8.11.0) + - FirebaseFirestore/AutodetectLeveldb (8.11.0): + - FirebaseFirestore/Base + - FirebaseFirestore/WithLeveldb + - FirebaseFirestore/Base (8.11.0) + - FirebaseFirestore/WithLeveldb (8.11.0): + - FirebaseFirestore/Base - FlutterMacOS (1.0.0) + - GoogleDataTransport (9.1.2): + - GoogleUtilities/Environment (~> 7.2) + - nanopb (~> 2.30908.0) + - PromisesObjC (< 3.0, >= 1.2) + - GoogleUtilities/Environment (7.7.0): + - PromisesObjC (< 3.0, >= 1.2) + - GoogleUtilities/Logger (7.7.0): + - GoogleUtilities/Environment + - nanopb (2.30908.0): + - nanopb/decode (= 2.30908.0) + - nanopb/encode (= 2.30908.0) + - nanopb/decode (2.30908.0) + - nanopb/encode (2.30908.0) - path_provider_macos (0.0.1): - FlutterMacOS + - PromisesObjC (2.0.0) + - shared_preferences_macos (0.0.1): + - FlutterMacOS DEPENDENCIES: - audioplayers (from `Flutter/ephemeral/.symlinks/plugins/audioplayers/macos`) + - cloud_firestore (from `Flutter/ephemeral/.symlinks/plugins/cloud_firestore/macos`) + - firebase_core (from `Flutter/ephemeral/.symlinks/plugins/firebase_core/macos`) + - FirebaseFirestore (from `https://github.com/invertase/firestore-ios-sdk-frameworks.git`, tag `8.11.0`) - FlutterMacOS (from `Flutter/ephemeral`) - path_provider_macos (from `Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos`) + - shared_preferences_macos (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_macos/macos`) + +SPEC REPOS: + trunk: + - Firebase + - FirebaseCore + - FirebaseCoreDiagnostics + - GoogleDataTransport + - GoogleUtilities + - nanopb + - PromisesObjC EXTERNAL SOURCES: audioplayers: :path: Flutter/ephemeral/.symlinks/plugins/audioplayers/macos + cloud_firestore: + :path: Flutter/ephemeral/.symlinks/plugins/cloud_firestore/macos + firebase_core: + :path: Flutter/ephemeral/.symlinks/plugins/firebase_core/macos + FirebaseFirestore: + :git: https://github.com/invertase/firestore-ios-sdk-frameworks.git + :tag: 8.11.0 FlutterMacOS: :path: Flutter/ephemeral path_provider_macos: :path: Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos + shared_preferences_macos: + :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_macos/macos + +CHECKOUT OPTIONS: + FirebaseFirestore: + :git: https://github.com/invertase/firestore-ios-sdk-frameworks.git + :tag: 8.11.0 SPEC CHECKSUMS: audioplayers: 8b48e22684b6e0d9df143b2d1bbd61dca9dab6b4 + cloud_firestore: b06c819c840a148bc51c8cc5719d5cf981ebc9ba + Firebase: 44dd9724c84df18b486639e874f31436eaa9a20c + firebase_core: 76a7538b389ae1231102dbbdd4f3772eec9abbf8 + FirebaseCore: 2f4f85b453cc8fea4bb2b37e370007d2bcafe3f0 + FirebaseCoreDiagnostics: 3b40dfadef5b90433a60ae01f01e90fe87aa76aa + FirebaseFirestore: 8a0c6a06219bbaad86c72bcb66688c28995dde84 FlutterMacOS: 57701585bf7de1b3fc2bb61f6378d73bbdea8424 + GoogleDataTransport: 629c20a4d363167143f30ea78320d5a7eb8bd940 + GoogleUtilities: e0913149f6b0625b553d70dae12b49fc62914fd1 + nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96 path_provider_macos: 160cab0d5461f0c0e02995469a98f24bdb9a3f1f + PromisesObjC: 68159ce6952d93e17b2dfe273b8c40907db5ba58 + shared_preferences_macos: a64dc611287ed6cbe28fd1297898db1336975727 -PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c +PODFILE CHECKSUM: 18cdccff4bca0076f1169092bd951115920b6156 COCOAPODS: 1.11.2 diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index 0d9947e..3f6219e 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -185,6 +185,7 @@ 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, 5C326AB95B07C7A0320DED7A /* [CP] Embed Pods Frameworks */, + 1BE3E7DBFD071237BBBC9E6D /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -254,6 +255,23 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 1BE3E7DBFD071237BBBC9E6D /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647;