From 9af3eb90aeccf024badd073e0494d57ac9e74b8f Mon Sep 17 00:00:00 2001 From: Alex Gustafsson Date: Sun, 26 Jul 2020 11:31:59 +0200 Subject: [PATCH 1/6] Add watch project --- app/FileProvider/Info.plist | 2 +- app/Info.plist | 2 +- iSH.xcconfig | 3 + iSH.xcodeproj/project.pbxproj | 407 +++++++++++++++++- .../Circular.imageset/Contents.json | 28 ++ .../Contents.json | 48 +++ .../Extra Large.imageset/Contents.json | 28 ++ .../Graphic Bezel.imageset/Contents.json | 28 ++ .../Graphic Circular.imageset/Contents.json | 28 ++ .../Graphic Corner.imageset/Contents.json | 28 ++ .../Contents.json | 28 ++ .../Modular.imageset/Contents.json | 28 ++ .../Utilitarian.imageset/Contents.json | 28 ++ watch Extension/Assets.xcassets/Contents.json | 6 + watch Extension/ContentView.swift | 20 + watch Extension/ExtensionDelegate.swift | 55 +++ watch Extension/HostingController.swift | 16 + watch Extension/Info.plist | 36 ++ watch Extension/NotificationController.swift | 33 ++ watch Extension/NotificationView.swift | 20 + .../Preview Assets.xcassets/Contents.json | 6 + watch Extension/PushNotificationPayload.apns | 20 + .../AppIcon.appiconset/Contents.json | 81 ++++ watch/Assets.xcassets/Contents.json | 6 + watch/Base.lproj/Interface.storyboard | 42 ++ watch/Info.plist | 33 ++ 26 files changed, 1056 insertions(+), 4 deletions(-) create mode 100644 watch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json create mode 100644 watch Extension/Assets.xcassets/Complication.complicationset/Contents.json create mode 100644 watch Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json create mode 100644 watch Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json create mode 100644 watch Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json create mode 100644 watch Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json create mode 100644 watch Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json create mode 100644 watch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json create mode 100644 watch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json create mode 100644 watch Extension/Assets.xcassets/Contents.json create mode 100644 watch Extension/ContentView.swift create mode 100644 watch Extension/ExtensionDelegate.swift create mode 100644 watch Extension/HostingController.swift create mode 100644 watch Extension/Info.plist create mode 100644 watch Extension/NotificationController.swift create mode 100644 watch Extension/NotificationView.swift create mode 100644 watch Extension/Preview Content/Preview Assets.xcassets/Contents.json create mode 100644 watch Extension/PushNotificationPayload.apns create mode 100644 watch/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 watch/Assets.xcassets/Contents.json create mode 100644 watch/Base.lproj/Interface.storyboard create mode 100644 watch/Info.plist diff --git a/app/FileProvider/Info.plist b/app/FileProvider/Info.plist index 18d8905f13..299405ecbf 100644 --- a/app/FileProvider/Info.plist +++ b/app/FileProvider/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 1.0 CFBundleVersion - 73 + $(PRODUCT_VERSION) NSExtension NSExtensionFileProviderDocumentGroup diff --git a/app/Info.plist b/app/Info.plist index 60a4de452a..07688702f7 100644 --- a/app/Info.plist +++ b/app/Info.plist @@ -17,7 +17,7 @@ CFBundleShortVersionString 1.0 CFBundleVersion - 73 + $(PRODUCT_VERSION) LSRequiresIPhoneOS NSLocationAlwaysAndWhenInUseUsageDescription diff --git a/iSH.xcconfig b/iSH.xcconfig index 0cc1b8b856..023c3370c4 100644 --- a/iSH.xcconfig +++ b/iSH.xcconfig @@ -5,3 +5,6 @@ ROOT_BUNDLE_IDENTIFIER = app.ish.iSH ISH_LOG = PRODUCT_APP_GROUP_IDENTIFIER = group.$(ROOT_BUNDLE_IDENTIFIER) + +// Change this to change all versions of the app and watch app +PRODUCT_VERSION = 73 diff --git a/iSH.xcodeproj/project.pbxproj b/iSH.xcodeproj/project.pbxproj index 858f58d9e1..89dc82f574 100644 --- a/iSH.xcodeproj/project.pbxproj +++ b/iSH.xcodeproj/project.pbxproj @@ -11,6 +11,17 @@ 650B337422EA235C00B4C03E /* PasteboardDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = 650B337322EA235C00B4C03E /* PasteboardDevice.m */; }; 8632A7BF219A59FB00F02325 /* UserPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 8632A7BE219A59FB00F02325 /* UserPreferences.m */; }; 9A28E4EA219A8B670073D200 /* AboutAppearanceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A28E4E9219A8B670073D200 /* AboutAppearanceViewController.m */; }; + B5A7C40924CD7D8C00747DC0 /* Interface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B5A7C40724CD7D8C00747DC0 /* Interface.storyboard */; }; + B5A7C40B24CD7D8C00747DC0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B5A7C40A24CD7D8C00747DC0 /* Assets.xcassets */; }; + B5A7C41224CD7D8C00747DC0 /* watch Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = B5A7C41124CD7D8C00747DC0 /* watch Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + B5A7C41724CD7D8C00747DC0 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A7C41624CD7D8C00747DC0 /* ContentView.swift */; }; + B5A7C41924CD7D8C00747DC0 /* HostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A7C41824CD7D8C00747DC0 /* HostingController.swift */; }; + B5A7C41B24CD7D8C00747DC0 /* ExtensionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A7C41A24CD7D8C00747DC0 /* ExtensionDelegate.swift */; }; + B5A7C41D24CD7D8C00747DC0 /* NotificationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A7C41C24CD7D8C00747DC0 /* NotificationController.swift */; }; + B5A7C41F24CD7D8C00747DC0 /* NotificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A7C41E24CD7D8C00747DC0 /* NotificationView.swift */; }; + B5A7C42124CD7D8D00747DC0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B5A7C42024CD7D8D00747DC0 /* Assets.xcassets */; }; + B5A7C42424CD7D8D00747DC0 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B5A7C42324CD7D8D00747DC0 /* Preview Assets.xcassets */; }; + B5A7C42924CD7D8D00747DC0 /* watch.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = B5A7C40524CD7D8B00747DC0 /* watch.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; BB0FC5921F980A6C00803272 /* Terminal.m in Sources */ = {isa = PBXBuildFile; fileRef = BB0FC5911F980A6B00803272 /* Terminal.m */; }; BB101B382364CF57000A93BC /* FontPickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BB101B372364CF57000A93BC /* FontPickerViewController.m */; }; BB10E5C3248DBA7B009C7A74 /* fakefsify.c in Sources */ = {isa = PBXBuildFile; fileRef = BB10E5C2248DBA7B009C7A74 /* fakefsify.c */; }; @@ -62,6 +73,20 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + B5A7C41324CD7D8C00747DC0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BB792B461F96D8E000FFB7A4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B5A7C41024CD7D8C00747DC0; + remoteInfo = "watch Extension"; + }; + B5A7C42724CD7D8D00747DC0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BB792B461F96D8E000FFB7A4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B5A7C40424CD7D8B00747DC0; + remoteInfo = watch; + }; BB10E5C7248DBAA1009C7A74 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BB10E0C1248DA5B0009C7A74 /* libarchive.xcodeproj */; @@ -107,6 +132,28 @@ /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ + B5A7C42A24CD7D8D00747DC0 /* Embed Watch Content */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(CONTENTS_FOLDER_PATH)/Watch"; + dstSubfolderSpec = 16; + files = ( + B5A7C42924CD7D8D00747DC0 /* watch.app in Embed Watch Content */, + ); + name = "Embed Watch Content"; + runOnlyForDeploymentPostprocessing = 0; + }; + B5A7C42D24CD7D8D00747DC0 /* Embed App Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + B5A7C41224CD7D8C00747DC0 /* watch Extension.appex in Embed App Extensions */, + ); + name = "Embed App Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; BB88F4A32154760800A341FD /* Embed App Extensions */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -139,6 +186,20 @@ 8632A7BE219A59FB00F02325 /* UserPreferences.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UserPreferences.m; sourceTree = ""; }; 9A28E4E8219A8B670073D200 /* AboutAppearanceViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AboutAppearanceViewController.h; sourceTree = ""; }; 9A28E4E9219A8B670073D200 /* AboutAppearanceViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AboutAppearanceViewController.m; sourceTree = ""; }; + B5A7C40524CD7D8B00747DC0 /* watch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = watch.app; sourceTree = BUILT_PRODUCTS_DIR; }; + B5A7C40824CD7D8C00747DC0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Interface.storyboard; sourceTree = ""; }; + B5A7C40A24CD7D8C00747DC0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + B5A7C40C24CD7D8C00747DC0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B5A7C41124CD7D8C00747DC0 /* watch Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "watch Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; + B5A7C41624CD7D8C00747DC0 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + B5A7C41824CD7D8C00747DC0 /* HostingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostingController.swift; sourceTree = ""; }; + B5A7C41A24CD7D8C00747DC0 /* ExtensionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionDelegate.swift; sourceTree = ""; }; + B5A7C41C24CD7D8C00747DC0 /* NotificationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationController.swift; sourceTree = ""; }; + B5A7C41E24CD7D8C00747DC0 /* NotificationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationView.swift; sourceTree = ""; }; + B5A7C42024CD7D8D00747DC0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + B5A7C42324CD7D8D00747DC0 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + B5A7C42524CD7D8D00747DC0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B5A7C42624CD7D8D00747DC0 /* PushNotificationPayload.apns */ = {isa = PBXFileReference; lastKnownFileType = text; path = PushNotificationPayload.apns; sourceTree = ""; }; BB0FC5901F980A6B00803272 /* Terminal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Terminal.h; sourceTree = ""; }; BB0FC5911F980A6B00803272 /* Terminal.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Terminal.m; sourceTree = ""; }; BB101B362364CF57000A93BC /* FontPickerViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FontPickerViewController.h; sourceTree = ""; }; @@ -350,6 +411,13 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + B5A7C40E24CD7D8C00747DC0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; BB792B4D1F96D90D00FFB7A4 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -385,6 +453,40 @@ path = proc; sourceTree = ""; }; + B5A7C40624CD7D8B00747DC0 /* watch */ = { + isa = PBXGroup; + children = ( + B5A7C40724CD7D8C00747DC0 /* Interface.storyboard */, + B5A7C40A24CD7D8C00747DC0 /* Assets.xcassets */, + B5A7C40C24CD7D8C00747DC0 /* Info.plist */, + ); + path = watch; + sourceTree = ""; + }; + B5A7C41524CD7D8C00747DC0 /* watch Extension */ = { + isa = PBXGroup; + children = ( + B5A7C41624CD7D8C00747DC0 /* ContentView.swift */, + B5A7C41824CD7D8C00747DC0 /* HostingController.swift */, + B5A7C41A24CD7D8C00747DC0 /* ExtensionDelegate.swift */, + B5A7C41C24CD7D8C00747DC0 /* NotificationController.swift */, + B5A7C41E24CD7D8C00747DC0 /* NotificationView.swift */, + B5A7C42024CD7D8D00747DC0 /* Assets.xcassets */, + B5A7C42524CD7D8D00747DC0 /* Info.plist */, + B5A7C42624CD7D8D00747DC0 /* PushNotificationPayload.apns */, + B5A7C42224CD7D8D00747DC0 /* Preview Content */, + ); + path = "watch Extension"; + sourceTree = ""; + }; + B5A7C42224CD7D8D00747DC0 /* Preview Content */ = { + isa = PBXGroup; + children = ( + B5A7C42324CD7D8D00747DC0 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; BB10E5C1248DB961009C7A74 /* Roots */ = { isa = PBXGroup; children = ( @@ -475,6 +577,8 @@ BB4A53931FAA393B00A72ACE /* most of the code */, BB18B27F1F97F2590059FCD8 /* Scripts */, BB9C7B88240A343400F5D4F0 /* iSH.xcconfig */, + B5A7C40624CD7D8B00747DC0 /* watch */, + B5A7C41524CD7D8C00747DC0 /* watch Extension */, BB792B511F96D90D00FFB7A4 /* Products */, BB792B7D1F96E32B00FFB7A4 /* Frameworks */, ); @@ -488,6 +592,8 @@ BBF124901FA7C3100088FB50 /* alpine.tar.gz */, BB13F7DC200AD81D003D1C4D /* libish.a */, BB88F4902154760800A341FD /* iSHFileProvider.appex */, + B5A7C40524CD7D8B00747DC0 /* watch.app */, + B5A7C41124CD7D8C00747DC0 /* watch Extension.appex */, ); name = Products; sourceTree = ""; @@ -827,6 +933,40 @@ /* End PBXLegacyTarget section */ /* Begin PBXNativeTarget section */ + B5A7C40424CD7D8B00747DC0 /* watch */ = { + isa = PBXNativeTarget; + buildConfigurationList = B5A7C43124CD7D8D00747DC0 /* Build configuration list for PBXNativeTarget "watch" */; + buildPhases = ( + B5A7C40324CD7D8B00747DC0 /* Resources */, + B5A7C42D24CD7D8D00747DC0 /* Embed App Extensions */, + ); + buildRules = ( + ); + dependencies = ( + B5A7C41424CD7D8C00747DC0 /* PBXTargetDependency */, + ); + name = watch; + productName = watch; + productReference = B5A7C40524CD7D8B00747DC0 /* watch.app */; + productType = "com.apple.product-type.application.watchapp2"; + }; + B5A7C41024CD7D8C00747DC0 /* watch Extension */ = { + isa = PBXNativeTarget; + buildConfigurationList = B5A7C43024CD7D8D00747DC0 /* Build configuration list for PBXNativeTarget "watch Extension" */; + buildPhases = ( + B5A7C40D24CD7D8C00747DC0 /* Sources */, + B5A7C40E24CD7D8C00747DC0 /* Frameworks */, + B5A7C40F24CD7D8C00747DC0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "watch Extension"; + productName = "watch Extension"; + productReference = B5A7C41124CD7D8C00747DC0 /* watch Extension.appex */; + productType = "com.apple.product-type.watchkit2-extension"; + }; BB13F7DB200AD81D003D1C4D /* libish */ = { isa = PBXNativeTarget; buildConfigurationList = BB13F7E2200AD81E003D1C4D /* Build configuration list for PBXNativeTarget "libish" */; @@ -853,6 +993,7 @@ BB4A53AC1FAA49CA00A72ACE /* Compile JavaScript */, BB792B4E1F96D90D00FFB7A4 /* Resources */, BB88F4A32154760800A341FD /* Embed App Extensions */, + B5A7C42A24CD7D8D00747DC0 /* Embed Watch Content */, ); buildRules = ( ); @@ -860,6 +1001,7 @@ BB10E5CB248DBAB7009C7A74 /* PBXTargetDependency */, BB13F7E7200AD874003D1C4D /* PBXTargetDependency */, BB88F49E2154760800A341FD /* PBXTargetDependency */, + B5A7C42824CD7D8D00747DC0 /* PBXTargetDependency */, ); name = iSH; productName = iSH; @@ -890,8 +1032,19 @@ isa = PBXProject; attributes = { CLASSPREFIX = ""; + LastSwiftUpdateCheck = 1160; LastUpgradeCheck = 1000; TargetAttributes = { + B5A7C40424CD7D8B00747DC0 = { + CreatedOnToolsVersion = 11.6; + DevelopmentTeam = CK5SXRTBR7; + ProvisioningStyle = Automatic; + }; + B5A7C41024CD7D8C00747DC0 = { + CreatedOnToolsVersion = 11.6; + DevelopmentTeam = CK5SXRTBR7; + ProvisioningStyle = Automatic; + }; BB13F7CA200ACC31003D1C4D = { CreatedOnToolsVersion = 9.2; DevelopmentTeam = CK5SXRTBR7; @@ -953,6 +1106,8 @@ BB13F7CA200ACC31003D1C4D /* Meson */, BB13F7D0200ACCA2003D1C4D /* Ninja */, BB13F7DB200AD81D003D1C4D /* libish */, + B5A7C40424CD7D8B00747DC0 /* watch */, + B5A7C41024CD7D8C00747DC0 /* watch Extension */, ); }; /* End PBXProject section */ @@ -968,6 +1123,24 @@ /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ + B5A7C40324CD7D8B00747DC0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B5A7C40B24CD7D8C00747DC0 /* Assets.xcassets in Resources */, + B5A7C40924CD7D8C00747DC0 /* Interface.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B5A7C40F24CD7D8C00747DC0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B5A7C42424CD7D8D00747DC0 /* Preview Assets.xcassets in Resources */, + B5A7C42124CD7D8D00747DC0 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; BB792B4E1F96D90D00FFB7A4 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -1045,6 +1218,18 @@ /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + B5A7C40D24CD7D8C00747DC0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B5A7C41924CD7D8C00747DC0 /* HostingController.swift in Sources */, + B5A7C41724CD7D8C00747DC0 /* ContentView.swift in Sources */, + B5A7C41D24CD7D8C00747DC0 /* NotificationController.swift in Sources */, + B5A7C41B24CD7D8C00747DC0 /* ExtensionDelegate.swift in Sources */, + B5A7C41F24CD7D8C00747DC0 /* NotificationView.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; BB792B4C1F96D90D00FFB7A4 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1094,6 +1279,16 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + B5A7C41424CD7D8C00747DC0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = B5A7C41024CD7D8C00747DC0 /* watch Extension */; + targetProxy = B5A7C41324CD7D8C00747DC0 /* PBXContainerItemProxy */; + }; + B5A7C42824CD7D8D00747DC0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = B5A7C40424CD7D8B00747DC0 /* watch */; + targetProxy = B5A7C42724CD7D8D00747DC0 /* PBXContainerItemProxy */; + }; BB10E5CB248DBAB7009C7A74 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = libarchive; @@ -1122,6 +1317,14 @@ /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ + B5A7C40724CD7D8C00747DC0 /* Interface.storyboard */ = { + isa = PBXVariantGroup; + children = ( + B5A7C40824CD7D8C00747DC0 /* Base */, + ); + name = Interface.storyboard; + sourceTree = ""; + }; BB792B591F96D90D00FFB7A4 /* Terminal.storyboard */ = { isa = PBXVariantGroup; children = ( @@ -1149,6 +1352,184 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ + B5A7C42B24CD7D8D00747DC0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = CK5SXRTBR7; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + IBSC_MODULE = watch_Extension; + INFOPLIST_FILE = watch/Info.plist; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "$(PRODUCT_BUNDLE_IDENTIFIER).watchkitapp"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 6.2; + }; + name = Debug; + }; + B5A7C42C24CD7D8D00747DC0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = CK5SXRTBR7; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + IBSC_MODULE = watch_Extension; + INFOPLIST_FILE = watch/Info.plist; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "$(PRODUCT_BUNDLE_IDENTIFIER).watchkitapp"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + VALIDATE_PRODUCT = YES; + WATCHOS_DEPLOYMENT_TARGET = 6.2; + }; + name = Release; + }; + B5A7C42E24CD7D8D00747DC0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_ASSET_PATHS = "\"watch Extension/Preview Content\""; + ENABLE_PREVIEWS = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INFOPLIST_FILE = "watch Extension/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "$(PRODUCT_BUNDLE_IDENTIFIER).watchkitapp.watchkitextension"; + PRODUCT_NAME = "${TARGET_NAME}"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 6.2; + }; + name = Debug; + }; + B5A7C42F24CD7D8D00747DC0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_ASSET_PATHS = "\"watch Extension/Preview Content\""; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_PREVIEWS = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INFOPLIST_FILE = "watch Extension/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "$(PRODUCT_BUNDLE_IDENTIFIER).watchkitapp.watchkitextension"; + PRODUCT_NAME = "${TARGET_NAME}"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + VALIDATE_PRODUCT = YES; + WATCHOS_DEPLOYMENT_TARGET = 6.2; + }; + name = Release; + }; BB13F7CC200ACC31003D1C4D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1163,6 +1544,7 @@ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; DEBUGGING_SYMBOLS = YES; @@ -1198,6 +1580,7 @@ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; @@ -1226,6 +1609,7 @@ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; DEBUGGING_SYMBOLS = YES; @@ -1262,6 +1646,7 @@ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; @@ -1385,7 +1770,7 @@ ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = "$(ROOT_BUNDLE_IDENTIFIER)"; SDKROOT = iphoneos; - VALID_ARCHS = arm64; + VALID_ARCHS = "$(ARCHS_STANDARD)"; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; @@ -1426,7 +1811,7 @@ MESON_BUILD_DIR = "$(CONFIGURATION_BUILD_DIR)/meson"; PRODUCT_BUNDLE_IDENTIFIER = "$(ROOT_BUNDLE_IDENTIFIER)"; SDKROOT = iphoneos; - VALID_ARCHS = arm64; + VALID_ARCHS = "$(ARCHS_STANDARD)"; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; @@ -1646,6 +2031,24 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + B5A7C43024CD7D8D00747DC0 /* Build configuration list for PBXNativeTarget "watch Extension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B5A7C42E24CD7D8D00747DC0 /* Debug */, + B5A7C42F24CD7D8D00747DC0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B5A7C43124CD7D8D00747DC0 /* Build configuration list for PBXNativeTarget "watch" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B5A7C42B24CD7D8D00747DC0 /* Debug */, + B5A7C42C24CD7D8D00747DC0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; BB13F7CB200ACC31003D1C4D /* Build configuration list for PBXLegacyTarget "Meson" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/watch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json b/watch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json new file mode 100644 index 0000000000..ed7de25e57 --- /dev/null +++ b/watch Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json @@ -0,0 +1,28 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">161" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/watch Extension/Assets.xcassets/Complication.complicationset/Contents.json b/watch Extension/Assets.xcassets/Complication.complicationset/Contents.json new file mode 100644 index 0000000000..df73a6bba4 --- /dev/null +++ b/watch Extension/Assets.xcassets/Complication.complicationset/Contents.json @@ -0,0 +1,48 @@ +{ + "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 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/watch Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json b/watch Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json new file mode 100644 index 0000000000..ed7de25e57 --- /dev/null +++ b/watch Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json @@ -0,0 +1,28 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">161" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/watch Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json b/watch Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json new file mode 100644 index 0000000000..ed7de25e57 --- /dev/null +++ b/watch Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json @@ -0,0 +1,28 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">161" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/watch Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json b/watch Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json new file mode 100644 index 0000000000..ed7de25e57 --- /dev/null +++ b/watch Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json @@ -0,0 +1,28 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">161" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/watch Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json b/watch Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json new file mode 100644 index 0000000000..ed7de25e57 --- /dev/null +++ b/watch Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json @@ -0,0 +1,28 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">161" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/watch Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json b/watch Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json new file mode 100644 index 0000000000..ed7de25e57 --- /dev/null +++ b/watch Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json @@ -0,0 +1,28 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">161" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/watch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json b/watch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json new file mode 100644 index 0000000000..ed7de25e57 --- /dev/null +++ b/watch Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json @@ -0,0 +1,28 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">161" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/watch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json b/watch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json new file mode 100644 index 0000000000..ed7de25e57 --- /dev/null +++ b/watch Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json @@ -0,0 +1,28 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">161" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/watch Extension/Assets.xcassets/Contents.json b/watch Extension/Assets.xcassets/Contents.json new file mode 100644 index 0000000000..73c00596a7 --- /dev/null +++ b/watch Extension/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/watch Extension/ContentView.swift b/watch Extension/ContentView.swift new file mode 100644 index 0000000000..253382f460 --- /dev/null +++ b/watch Extension/ContentView.swift @@ -0,0 +1,20 @@ +// +// ContentView.swift +// watch Extension +// +// Created by Alex Gustafsson on 2020-07-26. +// + +import SwiftUI + +struct ContentView: View { + var body: some View { + Text("Hello, World!") + } +} + +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + ContentView() + } +} diff --git a/watch Extension/ExtensionDelegate.swift b/watch Extension/ExtensionDelegate.swift new file mode 100644 index 0000000000..7309b81477 --- /dev/null +++ b/watch Extension/ExtensionDelegate.swift @@ -0,0 +1,55 @@ +// +// ExtensionDelegate.swift +// watch Extension +// +// Created by Alex Gustafsson on 2020-07-26. +// + +import WatchKit + +class ExtensionDelegate: NSObject, WKExtensionDelegate { + + func applicationDidFinishLaunching() { + // Perform any final initialization of your application. + } + + func applicationDidBecomeActive() { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillResignActive() { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, etc. + } + + func handle(_ backgroundTasks: Set) { + // Sent when the system needs to launch the application in the background to process tasks. Tasks arrive in a set, so loop through and process each one. + for task in backgroundTasks { + // Use a switch statement to check the task type + switch task { + case let backgroundTask as WKApplicationRefreshBackgroundTask: + // Be sure to complete the background task once you’re done. + backgroundTask.setTaskCompletedWithSnapshot(false) + case let snapshotTask as WKSnapshotRefreshBackgroundTask: + // Snapshot tasks have a unique completion call, make sure to set your expiration date + snapshotTask.setTaskCompleted(restoredDefaultState: true, estimatedSnapshotExpiration: Date.distantFuture, userInfo: nil) + case let connectivityTask as WKWatchConnectivityRefreshBackgroundTask: + // Be sure to complete the connectivity task once you’re done. + connectivityTask.setTaskCompletedWithSnapshot(false) + case let urlSessionTask as WKURLSessionRefreshBackgroundTask: + // Be sure to complete the URL session task once you’re done. + urlSessionTask.setTaskCompletedWithSnapshot(false) + case let relevantShortcutTask as WKRelevantShortcutRefreshBackgroundTask: + // Be sure to complete the relevant-shortcut task once you're done. + relevantShortcutTask.setTaskCompletedWithSnapshot(false) + case let intentDidRunTask as WKIntentDidRunRefreshBackgroundTask: + // Be sure to complete the intent-did-run task once you're done. + intentDidRunTask.setTaskCompletedWithSnapshot(false) + default: + // make sure to complete unhandled task types + task.setTaskCompletedWithSnapshot(false) + } + } + } + +} diff --git a/watch Extension/HostingController.swift b/watch Extension/HostingController.swift new file mode 100644 index 0000000000..cc5589f866 --- /dev/null +++ b/watch Extension/HostingController.swift @@ -0,0 +1,16 @@ +// +// HostingController.swift +// watch Extension +// +// Created by Alex Gustafsson on 2020-07-26. +// + +import WatchKit +import Foundation +import SwiftUI + +class HostingController: WKHostingController { + override var body: ContentView { + return ContentView() + } +} diff --git a/watch Extension/Info.plist b/watch Extension/Info.plist new file mode 100644 index 0000000000..c4561ca10c --- /dev/null +++ b/watch Extension/Info.plist @@ -0,0 +1,36 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + watch Extension + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(PRODUCT_VERSION) + NSExtension + + NSExtensionAttributes + + WKAppBundleIdentifier + $(ROOT_BUNDLE_IDENTIFIER).watchkitapp + + NSExtensionPointIdentifier + com.apple.watchkit + + WKExtensionDelegateClassName + $(PRODUCT_MODULE_NAME).ExtensionDelegate + + diff --git a/watch Extension/NotificationController.swift b/watch Extension/NotificationController.swift new file mode 100644 index 0000000000..b8d6b03ba6 --- /dev/null +++ b/watch Extension/NotificationController.swift @@ -0,0 +1,33 @@ +// +// NotificationController.swift +// watch Extension +// +// Created by Alex Gustafsson on 2020-07-26. +// + +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/watch Extension/NotificationView.swift b/watch Extension/NotificationView.swift new file mode 100644 index 0000000000..39005ce881 --- /dev/null +++ b/watch Extension/NotificationView.swift @@ -0,0 +1,20 @@ +// +// NotificationView.swift +// watch Extension +// +// Created by Alex Gustafsson on 2020-07-26. +// + +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/watch Extension/Preview Content/Preview Assets.xcassets/Contents.json b/watch Extension/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000000..73c00596a7 --- /dev/null +++ b/watch Extension/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/watch Extension/PushNotificationPayload.apns b/watch Extension/PushNotificationPayload.apns new file mode 100644 index 0000000000..c18b00ad94 --- /dev/null +++ b/watch 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/watch/Assets.xcassets/AppIcon.appiconset/Contents.json b/watch/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..d06b66af97 --- /dev/null +++ b/watch/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,81 @@ +{ + "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" : "appLauncher", + "scale" : "2x", + "size" : "40x40", + "subtype" : "38mm" + }, + { + "idiom" : "watch", + "role" : "appLauncher", + "scale" : "2x", + "size" : "44x44", + "subtype" : "40mm" + }, + { + "idiom" : "watch", + "role" : "appLauncher", + "scale" : "2x", + "size" : "50x50", + "subtype" : "44mm" + }, + { + "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-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/watch/Assets.xcassets/Contents.json b/watch/Assets.xcassets/Contents.json new file mode 100644 index 0000000000..73c00596a7 --- /dev/null +++ b/watch/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/watch/Base.lproj/Interface.storyboard b/watch/Base.lproj/Interface.storyboard new file mode 100644 index 0000000000..aa3bd9c21b --- /dev/null +++ b/watch/Base.lproj/Interface.storyboard @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/watch/Info.plist b/watch/Info.plist new file mode 100644 index 0000000000..4fe9b61530 --- /dev/null +++ b/watch/Info.plist @@ -0,0 +1,33 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + iSH + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(PRODUCT_VERSION) + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + + WKCompanionAppBundleIdentifier + $(ROOT_BUNDLE_IDENTIFIER) + WKWatchKitApp + + + From 83eaf595d2829851ed6f37bf5d8670a689bf72a1 Mon Sep 17 00:00:00 2001 From: Alex Gustafsson Date: Sun, 26 Jul 2020 11:51:58 +0200 Subject: [PATCH 2/6] Update hacking instructions for deploying to device --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 07ecc05e60..7f310e4e38 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,8 @@ You'll need these things to build the project: Open the project in Xcode, open iSH.xcconfig, and change `ROOT_BUNDLE_IDENTIFIER` to something unique. Then click Run. There are scripts that should do everything else automatically. If you run into any problems, open an issue and I'll try to help. +If you want to deploy the project onto your own devices, you'll need a valid developer account. Sign in to your account via Xcode: Xcode -> Preferences -> Accounts. Now go to the project settings and change the value for Signing > Development Team under Build Settings to your development team. To do this a bit more automatically, change the value for one project and then change all occurances of `CK5SXRTBR7` in `iSH.xcodeproj/project.pbxproj` to your development ID for all `DevelopmentTeam` fields. Your ID will be the one not matching `CK5SXRTBR7`. + ## Build command line tool for testing To set up your environment, cd to the project and run `meson build` to create a build directory in `build`. Then cd to the build directory and run `ninja`. From b89138c27ff2548845cdbcf4d6f2f8d662525985 Mon Sep 17 00:00:00 2001 From: Alex Gustafsson Date: Sun, 26 Jul 2020 12:15:46 +0200 Subject: [PATCH 3/6] Add icons --- watch/Assets.xcassets/.DS_Store | Bin 0 -> 6148 bytes watch/Assets.xcassets/AppIcon.appiconset/100.png | Bin 0 -> 2869 bytes watch/Assets.xcassets/AppIcon.appiconset/216.png | Bin 0 -> 3777 bytes watch/Assets.xcassets/AppIcon.appiconset/58.png | Bin 0 -> 1848 bytes watch/Assets.xcassets/AppIcon.appiconset/87.png | Bin 0 -> 3084 bytes .../AppIcon.appiconset/App Store.png | Bin 0 -> 7193 bytes .../AppIcon.appiconset/Contents.json | 11 +++++++++++ .../AppIcon.appiconset/Icon-172.png | Bin 0 -> 2259 bytes .../AppIcon.appiconset/Icon-196.png | Bin 0 -> 2473 bytes .../AppIcon.appiconset/Icon-48.png | Bin 0 -> 1015 bytes .../AppIcon.appiconset/Icon-55.png | Bin 0 -> 1339 bytes .../AppIcon.appiconset/Icon-80.png | Bin 0 -> 1192 bytes .../AppIcon.appiconset/Icon-88.png | Bin 0 -> 1340 bytes 13 files changed, 11 insertions(+) create mode 100644 watch/Assets.xcassets/.DS_Store create mode 100644 watch/Assets.xcassets/AppIcon.appiconset/100.png create mode 100644 watch/Assets.xcassets/AppIcon.appiconset/216.png create mode 100644 watch/Assets.xcassets/AppIcon.appiconset/58.png create mode 100644 watch/Assets.xcassets/AppIcon.appiconset/87.png create mode 100644 watch/Assets.xcassets/AppIcon.appiconset/App Store.png create mode 100644 watch/Assets.xcassets/AppIcon.appiconset/Icon-172.png create mode 100644 watch/Assets.xcassets/AppIcon.appiconset/Icon-196.png create mode 100644 watch/Assets.xcassets/AppIcon.appiconset/Icon-48.png create mode 100644 watch/Assets.xcassets/AppIcon.appiconset/Icon-55.png create mode 100644 watch/Assets.xcassets/AppIcon.appiconset/Icon-80.png create mode 100644 watch/Assets.xcassets/AppIcon.appiconset/Icon-88.png diff --git a/watch/Assets.xcassets/.DS_Store b/watch/Assets.xcassets/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..02799f8438eedaaac231e42a9d56a9f18b8fa117 GIT binary patch literal 6148 zcmeHK&5G1O5U!pbHE}?qc-RFG4IaD z1NZ=X-PQL{AHo;$ZdG@WxQv1)8KerTzv}9$>g4Otody6gnx;d5002Bx!j6y4Z-mB4 zSES=Sgu>J~1`P`CLJZ|fG&|Oj0b08o@DSIlgai0>{YuDPzlIE&WLB3+p%aY%o|Hvi zH-o`9(b?!;x_rg+ulD@jwVwYfn&?^7#LcuG#nm{t73FD`#MM!rHj~3l?HAcerk+%f z<0h+KQ1GGF1qN6w{_>yv)9wpcke%(oqzoF`HRT{ zfgiGw>kgOj6^*|l>LjXEq19WAU)EaIU}OfE0cK!L7;xK@*ISe4;m2SGn1S_Sfc6K8 zN*Fq9Et;(Z8~S~u@h%|=+H{v7lnz6OtwkI`5jGXkrV4k(5H=nC(#3@iTZ=Xwgqa!Z zxS55!p$IcO`lSg65nAMy8DIu3GO%I00iFN*f4=`;OyV9hzzqCX42bStv^T<6a%bzx x%h6dYQQx4FP+V*AX9^nTD8^ViiZ@Y>pkI=K7&>e%q6dY41Pl$_Fa!UTfgh>@X=4BY literal 0 HcmV?d00001 diff --git a/watch/Assets.xcassets/AppIcon.appiconset/100.png b/watch/Assets.xcassets/AppIcon.appiconset/100.png new file mode 100644 index 0000000000000000000000000000000000000000..6746a67423cc21deb055a31ffa61f0865bdfa725 GIT binary patch literal 2869 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 T2crtQ00000NkvXXu0mjf!AUu{ literal 0 HcmV?d00001 diff --git a/watch/Assets.xcassets/AppIcon.appiconset/216.png b/watch/Assets.xcassets/AppIcon.appiconset/216.png new file mode 100644 index 0000000000000000000000000000000000000000..188019c4ddcd783a9ca467ab582e20c2558ac7c4 GIT binary patch literal 3777 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 N(b~e!yvmet`(K%*xIzE` literal 0 HcmV?d00001 diff --git a/watch/Assets.xcassets/AppIcon.appiconset/58.png b/watch/Assets.xcassets/AppIcon.appiconset/58.png new file mode 100644 index 0000000000000000000000000000000000000000..7b398da5869c2a731483775ce3f4fc57df362049 GIT binary patch literal 1848 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 TIOQSWM+D~W;qTsj1e^U&>(nNU literal 0 HcmV?d00001 diff --git a/watch/Assets.xcassets/AppIcon.appiconset/Icon-196.png b/watch/Assets.xcassets/AppIcon.appiconset/Icon-196.png new file mode 100644 index 0000000000000000000000000000000000000000..f4dcd83aa955bc05ae9f47adbac5a22d856c4d0c GIT binary patch literal 2473 zcmcgudpMg}8jo4+C}DzLs5EJ+H3n6s7->el7a77?A) zwX!H?2hpw8N@=KT&_=6WVH1tI-^C?DM9dfS&(3uJ=seHP{Bh2C&U>EoeDC+3-{rmK zavrCyx?dFp0;!)p<8T33TNOiPCongaWrPBYQq%<;7R2O2r+|&}Wjkj(5a^#&HJRTI zV81K!jAs-Gq^7MHN}#*~9Uz7|>tJ^=#&>Q|c*l7Q*0Ff(bdW6XklV7p|EnBL|1u8s z2ZNHjgBC53r9rCe`Z6QyVp-P?mOV?S6ryD+Z~?nweblmBM%yc+`a*0Nt5Z+#v*O&b z8t%qA6E|%cO2NcgZ#b?Ndd@Hs@XABB0V>}dv2QZc{p9OT$iuHvZn&E(S7sr;rGu3! zK0HeL+|tt0)y?hhK6iI_(q}P8>|-8<^J^zNsPNqM^mNCns;Xb2y?nmjdR}d<73k^aI*hzJ>C%<~L+=lN*Wk&76OabJTcYgwtw>J84TG%DP-Y+>ngK9EAEczF#vJWz9aN^@Ym zJzbBqSy))Ok~&*+ZO)5@I~71|U!LfBbH%;ZCTcv*$Cir!366@%gwexI32YOd@S&gm z_YSL`PeSMd{e$Kw60vnfkX^cYb_jt>Y7+S6-yso(4%n0+7ZvN>hY{eE;>?P3WN6``UVERkf@}BU*;V5KTT442$aji1k?ERsTY&r?oN;0 zBpBceO(Z!O%G2x#7dJP39>YBFHmY1}(JKTf_^)A`XcpZ2VAQr0^P_lKv?YS3(flCS zX8ScMYa&FAN42kGbaXU{daE}0jlp`3{OyKhp(I&tUl)3a4o-YXUU;`MQV^z{(8cfX zH=Z5RD)e5A9EJKp}Dm_Wm zwG@Lz|Fwl>xkLPQrTM|kPj&M&37{7pJ`FLhOn75|yfdo@QHY`B!D!)3LZd0q`gBTA z&}kXZUpqPQgh4xg?4|z(Wq_ zjFiN&(%wAQy0#WGfJMcxnW2sNJ}ik%f~naee6Ft@rlQb7PC7X8ltMEF ze{^7|0wQEnjJ;E7G}_9KVHU5Gb>Q%F$aWS`+eDQK{5Pdy-@=wIy78E_{Wr3xaC7|dod<0U*8&U$dDpG{{I(Kqd$_ro zSth%iL6P^VyQKj(d`mbYIleW6vj#-*_dD=MS$3~b$Y4LH!Lw$}pDRonu*Jza{=agc u#V#9!1P9X;*8Nc}$$xb#IxF~Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf6951U69E94oEQKA1B^*TK~!i%)tE_7 z!!Qtqxgf&cQb53gQxB+=rBv)&7eHkxt2prg|A)i8$jGt#iefoZlaW5Do{r*7JQ+V{ zN-Qop)LAB`RLP-P1+lfY761JFSgftB(bycI&LH02-eT9f-7byI0lF+fJUu-r*RHRx zX>1PAtb%xce%8<3m?S`BbAUR7U~Bo12^Q z_xHEO($Z2~sZ`>@U|_MZun^a3wUPMc<>h!~Wo5*_zP?W9Bv5B2-rwJKff(D{+ly~+ zZ}rI7;o)I?b#k3 zY=3`Wot~cRkuhnzbWQ@zDiiEwl?3P$#mYzmdSpxzh$R6%GUl;wP-iBF!=awe*zWFb z(lTAcjb2<_=#jC5g9Dmazu%{G66msILS9yNa&n@MkB<}ZdvTluVk%#YGwm@ZZkPjs-dmi_HO=RVJWUu$iTS=8*)Fl1U@&GSNtGJoFK} zwg=Ri3D#|z&1NEZGhZxB9;GuK7zh+Ua-hy2SZQ@S9U2SR&V6@xM`H0{HLAJ&7_@LNF$)J1e%ov zPFU#IY5ug0>le|MaCCHJ5k*nbiQITxgU#syby|FWe(Hrah8-7W;o3MYgpG{t&`5&K z=>c693w9!dL`G+Et&m!X^>s;rN`^veq0*O-99-03FtET03!TFCK7rJ^9M21GRpt}002ovPDHLkV1i=q;@kiL literal 0 HcmV?d00001 diff --git a/watch/Assets.xcassets/AppIcon.appiconset/Icon-55.png b/watch/Assets.xcassets/AppIcon.appiconset/Icon-55.png new file mode 100644 index 0000000000000000000000000000000000000000..4fc7d5816c8242aecaeb4d149037956cc56ec199 GIT binary patch literal 1339 zcmV-B1;qM^P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf6951U69E94oEQKA1kg!DK~!i%-I~`+ z>|7MZ?Y&~JU@r(N7SIRFgIKVDqN4Ajf1nROh%X|Ff(ll|iWRINcAfKOWD2>w6Qt|WiqlNUx-rnBSJIeee6XN1KRcXy|rb98i6Qw+l&#d>W&P|+4CDJklttcGNgot;ff0fK92XwVeHE-o(Aa}Ey= zYl>kT8yjBN_5&4d;ppJ-SiZl%Yf~_+s;cU*k0rjR&CSi)C&Qkep44-Wjg4uFVFw2X zUf1>m6>Whm*4f!9y1TngAZbKJMTz$IcG1z%;ij#vO@xPss{vY%fiKRPm6hc+*3#1A zb!|UTk%GrBEiKIiCeM6zkkZ4#!o2WTCL}>c%G%nRczk>`fxjs8)j>J9zrQyfb8~Ye za&vR3zhtOLLA|ot;NT$j)hR10(>x7Bf(g1+!T$cfHa)}o`}?V{&Tp>@m`Fjkvf9AF z0QJ>Da8~>H_z1q>4i68t=^5rPIQCe6eSHOAaA>FM>gr4&oikq@WK#s_3GOBuVdgIx zD%t|6y`-c>-BR!bfnf}V+!J&yC8H_kHe920GU;Lz||4G9RrSq<3|!6|o6Qw&4*5_G{`US6sz15c13 z&;a8*=BeWkf#B-v>rFa97Zg;%AtUDH<*6-|Cs-{Y^PyZMCnuYJ;y7ee>oMp#gDPA4 zB04%+t%tZvI<>X6epeIe>FJ`iwbcZUW4=D1qBK~C0>fQm{yNwKwA$|OF7@>R6{Uf0 zM9J{l^!^yWTmITF>}^_Yb90mW`hbek2y|7zg8P*{6ko8%5_d9?$8u+9hx+<}iqa@5 zDiT*$S3>DL+?<}Csy!z2*BKfbG93fv=jW-f52*O-pp0OH$&&!;9~CKGU0v#aqRz<3 zi2DsGR^*;z0EHT*0ApD9=|B7W`qasz_*;+Z?d?@}#;n&45Gqpecv%gT!5CU9t6|>~ zMVT22Ior2H6b!?wCXAsuwwk}~boQ3#;o;$T zg2VeU)SB(>Z58~Eo)2S7OG~CPfHHs{acgVKq~l#4vR`#|wb%I;78ca)2kW&1go;jq ziqgOmXL@>C%*@QVnVOms2?+_*Uoupb29gRhNBlR#KeL@42#yX8`zXvD@mOMS1>HPS xyw2R*ocb>u%wIB8bP7~-3RH9oRCE9#;y-i#4RH`GKp_AC002ovPDHLkV1l;Ia{T}R literal 0 HcmV?d00001 diff --git a/watch/Assets.xcassets/AppIcon.appiconset/Icon-80.png b/watch/Assets.xcassets/AppIcon.appiconset/Icon-80.png new file mode 100644 index 0000000000000000000000000000000000000000..697a020e63249d5f16d9bc63ed1a345c6c71d3c9 GIT binary patch literal 1192 zcmeAS@N?(olHy`uVBq!ia0vp^0U*r51|<6gKdl8)jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85p>QL70(Y)*K0-8e2~n$B>G+x3kl|RU8G{{J*es*98QeVLaNw z)g^hRsUzteqiC_;iu%-dSu-=MUT&ZLsVeW*?$u4tPd~oh9lbj*pS}LiDvu9LUXA=y znB+BB?E<)J7Vx+wCMJf2gs?1}ztFI;(MaO+=g$|PKUYtwsF3L6Fj#3kzSnbK*qDsY-^_S9k8-JsR8?xq9_#t@7ex;poj@ zrk*%@)HUbqt-E(acW&Oi`Npi$l9DAwat<@C)~RpWuwg;bo%M!ap5!jwufWdEzR^^B z=~BfhE0w`+?lid|JnL)D*1dbz7Ww=8Z#3R54_M|`TU%>l zYb)#P>-*Gk-I66PPhY)ywPxp~OF>gtuUoh6*{M^fLe{NXb!wKjzJ9nR{{oR84w@et zC!IZW#;2sZdiL)%7ZtDHyT^BYhlITRcDp!#e|{NZ35}aO)Y_*`6}33VYI-Wn+Svz3S$teXi91^cSb1z=J_~OqWo9)btoY!sL8v69boI}%I zzj+g4Y4v@>(_OoEh3GLa@R{4*-d>?)kX>6F`!wcu$S+D+`cbr&Dyn3 z@5x#{(bCoq?c2BNMiDUSXt`@EME9Kwodh%z7&@SoVDRhLucGJsJElz&vpD8jUT$8a zvuN>R=Dwdw0c?-|{j;0Lb>>ojY~jv5dwSewmlhQ<9j_78XrB13O>6JvoUh@rZy!L? z9mqx3w_Sgq6TEZV-hU@OTlD5!-Y36k33K8ZU$^sK#rz8d-opQzb*2YaN*q27n6C*txtbFlv>lx z?PZpnoV-)@;>VALa!?vCrb%}mJXm1r{#?Pc@88#})4VemPvM5TldW0o zhqt%)#Yc~lfI1$Z&u5u(u)x>s{}a*sTRf|sO_>+)v_WFxl7s(_@S6RC0c_1-W+k&3 vCVqTcs0Yf{kaP$P>7@tQy&8}9zfeDACiSn$_?$7YbYbvx^>bP0l+XkK8Hp~U literal 0 HcmV?d00001 diff --git a/watch/Assets.xcassets/AppIcon.appiconset/Icon-88.png b/watch/Assets.xcassets/AppIcon.appiconset/Icon-88.png new file mode 100644 index 0000000000000000000000000000000000000000..e409067cd3beef5f8dfde46f7917c9209da8247e GIT binary patch literal 1340 zcmeAS@N?(olHy`uVBq!ia0vp^5g^RL1|$oo8khhn#^NA%Cx&(BWL^R}Ea{HEjtmSN z`?>!lvI6;>1s;*b3=G`DAk4@xYmNj^%|%Za$B>G+w{zV6b*u$i*PoCy+o14Vq3E3T zA-0eI>lwLKCY+dA_kGJQx8kLbzwJ2wF5M;aS4)Y;_A0(*v8lVCpT9p%!*SuFNBmk^ z{}v!oZjSNs@kN!DnNJ=)QhNE~#e!PprmnyZyLZpNaqG$zk+;%UW8=09mdGh2f`7Qy5T-UB$oAmm1wsLrQ z_{kS9G$3XiJ9ccz_U+d_{QdneUAW-z+l@t3v_8O4LZb5d^XHoB>FNI&-adJvl9`?D zoowjzISHt4^0#l_Ot$UbZEY@QzjVzy)oq(MZ!S7t>U1>W&HMN1mnZK$S$uVANL+mU zd6DATGiQ1x11&T@dPhu5OzV4$dI-<4bLafN3073s*7~}+xm}8gp7rhH$3V}^Im>Em zYeWA@oIZVeW>#Ktaq-mZb;4R~htocsKJ9&$E&TaGvu1mH`>P2iraSx~zTB9~X5h4m zV|tKe==`<5{{G81YHMrHOv?NG`7=awa&fWo&i(uS-@SXMq0!jh)^;gkNnGVdb93{P zH*Q2o?cTD*CAsDH?c1j^;$vc#7+&@8dd{fDws_@AO-Ts}k6*uk_j>${_SQL-*_pb3 z{W6a=>?>CMXzub`u*BBR&a9}SV#by&TQ2OYEGaF$_?mOax+zx$on6)Y`uaAlJb0(A zy*=~3O^zh{t@RQ7b`};V?DXl2N%Cb_;?S9I*&y*Mi`-vvu#Wn`Are!g+z#)9j@0hjvv`!DYk zbaYh@aCsn@!1PQ^)7Ck5dkWZr2M^@wYMBVnxUpo-wxf?E@7}sK>sZq98Amy;Zd7$X znsDP<^Zxz&o7b~X=Mimgyg23hy?ghv?p-|aXwQ<&ZL++79;Uc2PFW$rGy7m_j^tFJ znuToaZoGUwQZf?JVvU=kc($bq&e(Az;jEHTf|T3j&f~|AcOAUZm}bc2wp*fSZH1V! zg7r^PWr>q^b}KlaY`yWdwAZ!pP!h`#GjsF*#rmp_u1DoVdYEL^9WzuHw#W%e*)C;$ z@lDm$3Z2y}C0MuVFs0W$m3+g*vt_G%wb@x#pq(eZdDk&dx4FS;YT*oVh^d9aHqUh# zVu7a_b7T+JM_=5WY1L#LAn>5oLD=G1{E|Pef(O@y`%Yv!#sEsu7dfYF`7wRg+__61 z)UroTIk@7BD0d1=a>%Cp;h&Sms|(C{vp1{Fn>X)Lvr@;=ChKm&f~4hD2j?E;h-jLU zZXk9ivZvv>Y1q{#^SoQS{BE3Ec96sH#iNyu)(M^xyJN k*ICgD9B}c|YJaj`L;nG9)5$eyz!Hza)78&qol`;+07T|!6951J literal 0 HcmV?d00001 From 8dba14bb83f2d599214d20be8f2c7faf6ae2b5f4 Mon Sep 17 00:00:00 2001 From: Alex Gustafsson Date: Sun, 26 Jul 2020 13:37:58 +0200 Subject: [PATCH 4/6] Add mock UI for commands --- watch Extension/ContentView.swift | 24 +++++++++++++++- watch Extension/DetailView.swift | 46 +++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 watch Extension/DetailView.swift diff --git a/watch Extension/ContentView.swift b/watch Extension/ContentView.swift index 253382f460..15722ec7c8 100644 --- a/watch Extension/ContentView.swift +++ b/watch Extension/ContentView.swift @@ -8,8 +8,30 @@ import SwiftUI struct ContentView: View { + @State var showingDetail = false + @ObservedObject var detail = Detail() + var body: some View { - Text("Hello, World!") + List { + Button(action: { + self.detail.name = "Google DNS" + self.showingDetail.toggle() + }) { + Text("Google DNS") + }.sheet(isPresented: $showingDetail) { + DetailView(name: self.$detail.name) + } + + Button(action: { + self.detail.name = "Ping servers" + self.showingDetail.toggle() + }) { + Text("Ping servers") + }.sheet(isPresented: $showingDetail) { + DetailView(name: self.$detail.name) + } + } + .navigationBarTitle("iSH") } } diff --git a/watch Extension/DetailView.swift b/watch Extension/DetailView.swift new file mode 100644 index 0000000000..4f0c592b47 --- /dev/null +++ b/watch Extension/DetailView.swift @@ -0,0 +1,46 @@ +// +// DetailView.swift +// watch Extension +// +// Created by Alex Gustafsson on 2020-07-26. +// + +import SwiftUI + +class Detail: ObservableObject { + @Published var name: String = "" +} + +struct DetailView: View { + @Binding var name: String + + var body: some View { + ScrollView(.vertical) { + VStack { + Text(name) + .multilineTextAlignment(.leading) + .frame(minWidth: 0, maxWidth: .infinity, alignment: .topLeading) + Divider() + VStack { + Text("$ output from iSH displayed here") + .frame(minWidth: 0, maxWidth: .infinity, alignment: .topLeading) + ForEach(0 ..< 100) { number in + Text("line by line") + .padding(.top, 5.0) + .frame(minWidth: 0, maxWidth: .infinity, alignment: .topLeading) + } + } + .background(/*@START_MENU_TOKEN@*/Color.white/*@END_MENU_TOKEN@*/) + .frame(minWidth: 0, maxWidth: .infinity, alignment: .topLeading) + .foregroundColor(Color.black) + .font(Font.body) + } + } + } +} + +struct DetailView_Previews: PreviewProvider { + static var previews: some View { + DetailView(name: .constant("Example action")) + } +} From aecb92cd2b3e833fd62ced84f1924eb1593ceafd Mon Sep 17 00:00:00 2001 From: Alex Gustafsson Date: Sun, 26 Jul 2020 15:53:08 +0200 Subject: [PATCH 5/6] Implement basic communication --- app/AppDelegate.m | 62 ++++++++++++++++++- iSH.xcodeproj/project.pbxproj | 4 ++ watch Extension/ContentView.swift | 31 ++++++++++ watch Extension/ErrorView.swift | 28 +++++++++ watch Extension/HostingController.swift | 32 +++++++++- .../watch ExtensionRelease.entitlements | 10 +++ watch/watchRelease.entitlements | 10 +++ 7 files changed, 175 insertions(+), 2 deletions(-) create mode 100644 watch Extension/ErrorView.swift create mode 100644 watch Extension/watch ExtensionRelease.entitlements create mode 100644 watch/watchRelease.entitlements diff --git a/app/AppDelegate.m b/app/AppDelegate.m index 1ccec5bdab..38596c6c47 100644 --- a/app/AppDelegate.m +++ b/app/AppDelegate.m @@ -19,13 +19,14 @@ #import "Roots.h" #import "TerminalViewController.h" #import "UserPreferences.h" +#import #include "kernel/init.h" #include "kernel/calls.h" #include "fs/dyndev.h" #include "fs/devices.h" #include "fs/path.h" -@interface AppDelegate () +@interface AppDelegate () @property BOOL exiting; @property NSString *unameVersion; @@ -203,6 +204,15 @@ + (int)bootError { } - (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + if(WCSession.isSupported){ + WCSession* session = WCSession.defaultSession; + session.delegate = self; + [session activateSession]; + NSLog(@"Started watch session"); + } else { + NSLog(@"Watch communication not supported"); + } + NSUserDefaults *defaults = NSUserDefaults.standardUserDefaults; if ([defaults boolForKey:@"hail mary"]) { [defaults removeObjectForKey:kPreferenceBootCommandKey]; @@ -289,6 +299,56 @@ - (void)applicationDidEnterBackground:(UIApplication *)application { exit(0); } +- (void)session:(WCSession *)session didReceiveMessage:(NSDictionary *)message replyHandler:(void(^)(NSDictionary *replyMessage))replyHandler +{ + NSLog(@"Received message from watch"); + + if (message) { + NSString* text = [message objectForKey:@"message"]; + + NSLog(@"Got message string %@", text); + } +} + +-(void)sessionWatchStateDidChange:(nonnull WCSession *)session +{ + + if(WCSession.isSupported){ + WCSession* session = WCSession.defaultSession; + session.delegate = self; + [session activateSession]; + + + if(session.reachable){ + NSLog(@"session.reachable"); + } + + if(session.paired){ + NSLog(@"watch is paired"); + if(session.isWatchAppInstalled){ + NSLog(@"watch app is installed"); + if(session.watchDirectoryURL != nil) { + NSLog(@"watch got directory URL %@", session.watchDirectoryURL); + } + } + } + + + } +} + +- (void)session:(nonnull WCSession *)session activationDidCompleteWithState:(WCSessionActivationState)activationState error:(nullable NSError *)error { + NSLog(@"Watch session became active with status: %ld", activationState); +} + +- (void)sessionDidBecomeInactive:(nonnull WCSession *)session { + NSLog(@"Watch session became inactive"); +} + +- (void)sessionDidDeactivate:(nonnull WCSession *)session { + NSLog(@"Watch session became deactivated"); +} + @end NSString *const ProcessExitedNotification = @"ProcessExitedNotification"; diff --git a/iSH.xcodeproj/project.pbxproj b/iSH.xcodeproj/project.pbxproj index 89dc82f574..f04d342184 100644 --- a/iSH.xcodeproj/project.pbxproj +++ b/iSH.xcodeproj/project.pbxproj @@ -1223,8 +1223,10 @@ buildActionMask = 2147483647; files = ( B5A7C41924CD7D8C00747DC0 /* HostingController.swift in Sources */, + B5CD9F3A24CD96BE00DE7A15 /* DetailView.swift in Sources */, B5A7C41724CD7D8C00747DC0 /* ContentView.swift in Sources */, B5A7C41D24CD7D8C00747DC0 /* NotificationController.swift in Sources */, + B5CD9F3E24CDB50400DE7A15 /* ErrorView.swift in Sources */, B5A7C41B24CD7D8C00747DC0 /* ExtensionDelegate.swift in Sources */, B5A7C41F24CD7D8C00747DC0 /* NotificationView.swift in Sources */, ); @@ -1416,6 +1418,7 @@ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = watch/watchRelease.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; @@ -1504,6 +1507,7 @@ CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = "watch Extension/watch ExtensionRelease.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; diff --git a/watch Extension/ContentView.swift b/watch Extension/ContentView.swift index 15722ec7c8..c1b43f3f3b 100644 --- a/watch Extension/ContentView.swift +++ b/watch Extension/ContentView.swift @@ -6,20 +6,51 @@ // import SwiftUI +import WatchConnectivity +import WatchConnectivity struct ContentView: View { @State var showingDetail = false @ObservedObject var detail = Detail() + + @State var showingError = false + @State var errorMessage: String = "" + @State var error: Error? = nil var body: some View { List { Button(action: { self.detail.name = "Google DNS" self.showingDetail.toggle() + + if WCSession.isSupported() { + if WCSession.default.isReachable { + WCSession.default.sendMessage(["message": "Hello, world!"], replyHandler: { reply -> Void in + print("Got reply: \(reply)") + }, errorHandler: { (error) -> Void in + self.errorMessage = "Sending message failed" + self.error = error + self.showingDetail = false + self.showingError = true + }) + } else { + self.errorMessage = "Unable to communicate with iSH - not reachable" + self.error = nil + self.showingDetail = false + self.showingError = true + } + } else { + self.errorMessage = "WatchConnectivity is not supported" + self.error = nil + self.showingDetail = false + self.showingError = true + } }) { Text("Google DNS") }.sheet(isPresented: $showingDetail) { DetailView(name: self.$detail.name) + }.sheet(isPresented: $showingError) { + ErrorView(message: self.errorMessage, error: self.error) } Button(action: { diff --git a/watch Extension/ErrorView.swift b/watch Extension/ErrorView.swift new file mode 100644 index 0000000000..0d0593702b --- /dev/null +++ b/watch Extension/ErrorView.swift @@ -0,0 +1,28 @@ +// +// ErrorView.swift +// watch Extension +// +// Created by Alex Gustafsson on 2020-07-26. +// + +import SwiftUI + +struct ErrorView: View { + var message: String + var error: Error? + + var body: some View { + VStack { + Text(self.message) + if self.error != nil { + Text(self.error!.localizedDescription) + } + } + } +} + +struct ErrorView_Previews: PreviewProvider { + static var previews: some View { + ErrorView(message: "Example error", error: NSError(domain: "Example error", code: 69)) + } +} diff --git a/watch Extension/HostingController.swift b/watch Extension/HostingController.swift index cc5589f866..32a9abc1e0 100644 --- a/watch Extension/HostingController.swift +++ b/watch Extension/HostingController.swift @@ -8,8 +8,38 @@ import WatchKit import Foundation import SwiftUI +import WatchConnectivity -class HostingController: WKHostingController { +class HostingController: WKHostingController, WCSessionDelegate { + var wcSession : WCSession! + + func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) { + print("activationDidComplete", activationState) + } + + func session(_ session: WCSession, didReceiveMessage message: [String : Any]) { + let text = message["message"] as! String + print("Received message \(text)") + } + + override func willActivate() { + super.willActivate() + + if WCSession.isSupported() { + print("WCSession is supported. Activating watch communication session") + self.wcSession = WCSession.default + self.wcSession.delegate = self + self.wcSession.activate() + print("Watch communication session active") + } else { + print("Watch communication is not supported") + } + } + + func sessionReachabilityDidChange(_ session: WCSession) { + print("Watch companion reachability changed to \(session.isReachable)") + } + override var body: ContentView { return ContentView() } diff --git a/watch Extension/watch ExtensionRelease.entitlements b/watch Extension/watch ExtensionRelease.entitlements new file mode 100644 index 0000000000..b3554e4b37 --- /dev/null +++ b/watch Extension/watch ExtensionRelease.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.application-groups + + $(PRODUCT_APP_GROUP_IDENTIFIER) + + + diff --git a/watch/watchRelease.entitlements b/watch/watchRelease.entitlements new file mode 100644 index 0000000000..b3554e4b37 --- /dev/null +++ b/watch/watchRelease.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.application-groups + + $(PRODUCT_APP_GROUP_IDENTIFIER) + + + From 8c3d8ca0b4474ba4ec5c1eb2b6bfd01c260b5860 Mon Sep 17 00:00:00 2001 From: Alex Gustafsson Date: Sun, 26 Jul 2020 17:40:49 +0200 Subject: [PATCH 6/6] Implement sending of commands from watchOS --- app/AppDelegate.m | 18 ++++++++++++++++-- app/TerminalViewController.h | 1 + app/TerminalViewController.m | 1 - .../xcdebugger/Breakpoints_v2.xcbkptlist | 10 ---------- watch Extension/ContentView.swift | 2 +- 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/app/AppDelegate.m b/app/AppDelegate.m index 38596c6c47..cbd9053d4f 100644 --- a/app/AppDelegate.m +++ b/app/AppDelegate.m @@ -304,9 +304,23 @@ - (void)session:(WCSession *)session didReceiveMessage:(NSDictionary @property (weak, nonatomic) IBOutlet UIButton *hideKeyboardButton; @property int sessionPid; -@property (nonatomic) Terminal *sessionTerminal; @property int sessionTerminalNumber; @property BOOL ignoreKeyboardMotion; diff --git a/iSH.xcodeproj/xcshareddata/xcdebugger/Breakpoints_v2.xcbkptlist b/iSH.xcodeproj/xcshareddata/xcdebugger/Breakpoints_v2.xcbkptlist index 7d7be4d38c..c854a4e2a6 100644 --- a/iSH.xcodeproj/xcshareddata/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/iSH.xcodeproj/xcshareddata/xcdebugger/Breakpoints_v2.xcbkptlist @@ -22,16 +22,6 @@ - - diff --git a/watch Extension/ContentView.swift b/watch Extension/ContentView.swift index c1b43f3f3b..7643cef143 100644 --- a/watch Extension/ContentView.swift +++ b/watch Extension/ContentView.swift @@ -25,7 +25,7 @@ struct ContentView: View { if WCSession.isSupported() { if WCSession.default.isReachable { - WCSession.default.sendMessage(["message": "Hello, world!"], replyHandler: { reply -> Void in + WCSession.default.sendMessage(["command": "ls -l\n"], replyHandler: { reply -> Void in print("Got reply: \(reply)") }, errorHandler: { (error) -> Void in self.errorMessage = "Sending message failed"