diff --git a/iphone/Maps/Maps.xcodeproj/project.pbxproj b/iphone/Maps/Maps.xcodeproj/project.pbxproj index 626c8e6813..ff3387f478 100644 --- a/iphone/Maps/Maps.xcodeproj/project.pbxproj +++ b/iphone/Maps/Maps.xcodeproj/project.pbxproj @@ -475,10 +475,24 @@ ED1080A72B791CFE0023F27E /* SocialMediaCollectionViewHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED1080A62B791CFE0023F27E /* SocialMediaCollectionViewHeader.swift */; }; ED1263AB2B6F99F900AD99F3 /* UIView+AddSeparator.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED1263AA2B6F99F900AD99F3 /* UIView+AddSeparator.swift */; }; ED1ADA332BC6B1B40029209F /* CarPlayServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED1ADA322BC6B1B40029209F /* CarPlayServiceTests.swift */; }; + ED2D72382D1315B100660FBF /* TrackRecordingActivityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED2D72372D1315B100660FBF /* TrackRecordingActivityManager.swift */; }; + ED2D74382D14337500660FBF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = ED2D74342D14337500660FBF /* Assets.xcassets */; }; + ED2D74392D14337500660FBF /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = ED2D74352D14337500660FBF /* Info.plist */; }; + ED2D743A2D14337500660FBF /* AppLogo.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED2D742C2D14337500660FBF /* AppLogo.swift */; }; + ED2D743B2D14337500660FBF /* LiveActivityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED2D742D2D14337500660FBF /* LiveActivityManager.swift */; }; + ED2D743C2D14337500660FBF /* StatisticDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED2D742E2D14337500660FBF /* StatisticDetailView.swift */; }; + ED2D743D2D14337500660FBF /* StatisticValueView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED2D742F2D14337500660FBF /* StatisticValueView.swift */; }; + ED2D743E2D14337500660FBF /* TrackRecordingLiveActivityAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED2D74302D14337500660FBF /* TrackRecordingLiveActivityAttributes.swift */; }; + ED2D743F2D14337500660FBF /* TrackRecordingLiveActivityConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED2D74312D14337500660FBF /* TrackRecordingLiveActivityConfiguration.swift */; }; + ED2D74402D14337500660FBF /* TrackRecordingLiveActivityView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED2D74322D14337500660FBF /* TrackRecordingLiveActivityView.swift */; }; + ED2D74412D14337500660FBF /* OMapsWidgetExtensionBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED2D74362D14337500660FBF /* OMapsWidgetExtensionBundle.swift */; }; ED2E328E2D10500900807A08 /* TrackRecordingButtonArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED46DD922D06F804007CACD6 /* TrackRecordingButtonArea.swift */; }; ED2E32912D10501700807A08 /* TrackRecordingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED49D76F2CF0E3A8004AF27E /* TrackRecordingViewController.swift */; }; ED3EAC202B03C88100220A4A /* BottomTabBarButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3EAC1F2B03C88100220A4A /* BottomTabBarButton.swift */; }; ED43B8BD2C12063500D07BAA /* DocumentPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED43B8BC2C12063500D07BAA /* DocumentPicker.swift */; }; + ED46DDCE2D098A0B007CACD6 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED46DDCD2D098A0B007CACD6 /* WidgetKit.framework */; }; + ED46DDD02D098A0B007CACD6 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED46DDCF2D098A0B007CACD6 /* SwiftUI.framework */; }; + ED46DDE12D098A0C007CACD6 /* OMapsWidgetExtensionExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = ED46DDCC2D098A0B007CACD6 /* OMapsWidgetExtensionExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; ED4DC7772CAEDECC0029B338 /* ProductsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED4DC7752CAEDECC0029B338 /* ProductsViewModel.swift */; }; ED4DC7782CAEDECC0029B338 /* ProductButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED4DC7732CAEDECC0029B338 /* ProductButton.swift */; }; ED4DC7792CAEDECC0029B338 /* ProductsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED4DC7742CAEDECC0029B338 /* ProductsViewController.swift */; }; @@ -694,6 +708,13 @@ remoteGlobalIDString = 6741A93D1BF340DE002C974C; remoteInfo = OMaps; }; + ED46DDDF2D098A0C007CACD6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = ED46DDCB2D098A0B007CACD6; + remoteInfo = OMapsWidgetExtensionExtension; + }; FA456C4626BDCC8E00B83C20 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = FA456C4026BDCC8E00B83C20 /* shaders.xcodeproj */; @@ -738,6 +759,17 @@ name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; + ED46DDE22D098A0C007CACD6 /* Embed Foundation Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + ED46DDE12D098A0C007CACD6 /* OMapsWidgetExtensionExtension.appex in Embed Foundation Extensions */, + ); + name = "Embed Foundation Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; FA456C4E26BDCCC300B83C20 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -1406,9 +1438,23 @@ ED1080A62B791CFE0023F27E /* SocialMediaCollectionViewHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocialMediaCollectionViewHeader.swift; sourceTree = ""; }; ED1263AA2B6F99F900AD99F3 /* UIView+AddSeparator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+AddSeparator.swift"; sourceTree = ""; }; ED1ADA322BC6B1B40029209F /* CarPlayServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarPlayServiceTests.swift; sourceTree = ""; }; + ED2D72372D1315B100660FBF /* TrackRecordingActivityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackRecordingActivityManager.swift; sourceTree = ""; }; + ED2D742C2D14337500660FBF /* AppLogo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLogo.swift; sourceTree = ""; }; + ED2D742D2D14337500660FBF /* LiveActivityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveActivityManager.swift; sourceTree = ""; }; + ED2D742E2D14337500660FBF /* StatisticDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatisticDetailView.swift; sourceTree = ""; }; + ED2D742F2D14337500660FBF /* StatisticValueView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatisticValueView.swift; sourceTree = ""; }; + ED2D74302D14337500660FBF /* TrackRecordingLiveActivityAttributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackRecordingLiveActivityAttributes.swift; sourceTree = ""; }; + ED2D74312D14337500660FBF /* TrackRecordingLiveActivityConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackRecordingLiveActivityConfiguration.swift; sourceTree = ""; }; + ED2D74322D14337500660FBF /* TrackRecordingLiveActivityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackRecordingLiveActivityView.swift; sourceTree = ""; }; + ED2D74342D14337500660FBF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + ED2D74352D14337500660FBF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + ED2D74362D14337500660FBF /* OMapsWidgetExtensionBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OMapsWidgetExtensionBundle.swift; sourceTree = ""; }; ED3EAC1F2B03C88100220A4A /* BottomTabBarButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomTabBarButton.swift; sourceTree = ""; }; ED43B8BC2C12063500D07BAA /* DocumentPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentPicker.swift; sourceTree = ""; }; ED46DD922D06F804007CACD6 /* TrackRecordingButtonArea.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackRecordingButtonArea.swift; sourceTree = ""; }; + ED46DDCC2D098A0B007CACD6 /* OMapsWidgetExtensionExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = OMapsWidgetExtensionExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + ED46DDCD2D098A0B007CACD6 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; }; + ED46DDCF2D098A0B007CACD6 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; }; ED48BBB817C2B1E2003E7E92 /* CircleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CircleView.h; sourceTree = ""; }; ED48BBB917C2B1E2003E7E92 /* CircleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CircleView.m; sourceTree = ""; }; ED49D76F2CF0E3A8004AF27E /* TrackRecordingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackRecordingViewController.swift; sourceTree = ""; }; @@ -1823,6 +1869,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + ED46DDC92D098A0B007CACD6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ED46DDD02D098A0B007CACD6 /* SwiftUI.framework in Frameworks */, + ED46DDCE2D098A0B007CACD6 /* WidgetKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -1864,6 +1919,7 @@ children = ( 6741AA5D1BF340DE002C974C /* Organic Maps (Debug).app */, ED097E762BB80C320006ED01 /* OMapsTests.xctest */, + ED46DDCC2D098A0B007CACD6 /* OMapsWidgetExtensionExtension.appex */, ); name = Products; sourceTree = ""; @@ -1890,6 +1946,7 @@ 29B97317FDCFA39411CA2CEA /* Resources */, F6E2FBFB1E097B9F0083EBEC /* UI */, ED1ADA312BC6B19E0029209F /* Tests */, + ED2D74372D14337500660FBF /* OMapsWidgetExtension */, ); indentWidth = 2; name = Maps; @@ -1958,6 +2015,8 @@ FA853BD026BC3B8A0026D455 /* libsuccinct.a */, FA853BA626BC3ACE0026D455 /* CoreApi.framework */, FA14E683276014C10066E453 /* libz.1.tbd */, + ED46DDCD2D098A0B007CACD6 /* WidgetKit.framework */, + ED46DDCF2D098A0B007CACD6 /* SwiftUI.framework */, ); name = Frameworks; sourceTree = ""; @@ -3124,6 +3183,31 @@ path = Tests; sourceTree = ""; }; + ED2D74332D14337500660FBF /* LiveActivity */ = { + isa = PBXGroup; + children = ( + ED2D742C2D14337500660FBF /* AppLogo.swift */, + ED2D742D2D14337500660FBF /* LiveActivityManager.swift */, + ED2D742E2D14337500660FBF /* StatisticDetailView.swift */, + ED2D742F2D14337500660FBF /* StatisticValueView.swift */, + ED2D74302D14337500660FBF /* TrackRecordingLiveActivityAttributes.swift */, + ED2D74312D14337500660FBF /* TrackRecordingLiveActivityConfiguration.swift */, + ED2D74322D14337500660FBF /* TrackRecordingLiveActivityView.swift */, + ); + path = LiveActivity; + sourceTree = ""; + }; + ED2D74372D14337500660FBF /* OMapsWidgetExtension */ = { + isa = PBXGroup; + children = ( + ED2D74332D14337500660FBF /* LiveActivity */, + ED2D74342D14337500660FBF /* Assets.xcassets */, + ED2D74352D14337500660FBF /* Info.plist */, + ED2D74362D14337500660FBF /* OMapsWidgetExtensionBundle.swift */, + ); + path = OMapsWidgetExtension; + sourceTree = ""; + }; ED43B8B92C12061600D07BAA /* DocumentPicker */ = { isa = PBXGroup; children = ( @@ -3972,11 +4056,13 @@ 6741A9A01BF340DE002C974C /* Sources */, 6741AA311BF340DE002C974C /* Frameworks */, 4740184523F5BDE900A93C81 /* Embed Frameworks */, + ED46DDE22D098A0C007CACD6 /* Embed Foundation Extensions */, ); buildRules = ( ); dependencies = ( FA456C4D26BDCC9400B83C20 /* PBXTargetDependency */, + ED46DDE02D098A0C007CACD6 /* PBXTargetDependency */, ); name = OMaps; productName = Maps; @@ -4001,6 +4087,25 @@ productReference = ED097E762BB80C320006ED01 /* OMapsTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + ED46DDCB2D098A0B007CACD6 /* OMapsWidgetExtensionExtension */ = { + isa = PBXNativeTarget; + buildConfigurationList = ED46DDE62D098A0C007CACD6 /* Build configuration list for PBXNativeTarget "OMapsWidgetExtensionExtension" */; + buildPhases = ( + ED46DDC82D098A0B007CACD6 /* Sources */, + ED46DDC92D098A0B007CACD6 /* Frameworks */, + ED46DDCA2D098A0B007CACD6 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = OMapsWidgetExtensionExtension; + packageProductDependencies = ( + ); + productName = OMapsWidgetExtensionExtension; + productReference = ED46DDCC2D098A0B007CACD6 /* OMapsWidgetExtensionExtension.appex */; + productType = "com.apple.product-type.app-extension"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -4023,6 +4128,9 @@ }; }; }; + ED46DDCB2D098A0B007CACD6 = { + CreatedOnToolsVersion = 16.0; + }; }; }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Maps" */; @@ -4089,6 +4197,7 @@ targets = ( 6741A93D1BF340DE002C974C /* OMaps */, ED097E752BB80C320006ED01 /* OMapsTests */, + ED46DDCB2D098A0B007CACD6 /* OMapsWidgetExtensionExtension */, ); }; /* End PBXProject section */ @@ -4294,6 +4403,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + ED46DDCA2D098A0B007CACD6 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ED2D74382D14337500660FBF /* Assets.xcassets in Resources */, + ED2D74392D14337500660FBF /* Info.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -4783,6 +4901,21 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + ED46DDC82D098A0B007CACD6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ED2D743A2D14337500660FBF /* AppLogo.swift in Sources */, + ED2D743B2D14337500660FBF /* LiveActivityManager.swift in Sources */, + ED2D743C2D14337500660FBF /* StatisticDetailView.swift in Sources */, + ED2D743D2D14337500660FBF /* StatisticValueView.swift in Sources */, + ED2D743E2D14337500660FBF /* TrackRecordingLiveActivityAttributes.swift in Sources */, + ED2D743F2D14337500660FBF /* TrackRecordingLiveActivityConfiguration.swift in Sources */, + ED2D74402D14337500660FBF /* TrackRecordingLiveActivityView.swift in Sources */, + ED2D74412D14337500660FBF /* OMapsWidgetExtensionBundle.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -4791,6 +4924,11 @@ target = 6741A93D1BF340DE002C974C /* OMaps */; targetProxy = ED097E7A2BB80C320006ED01 /* PBXContainerItemProxy */; }; + ED46DDE02D098A0C007CACD6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = ED46DDCB2D098A0B007CACD6 /* OMapsWidgetExtensionExtension */; + targetProxy = ED46DDDF2D098A0C007CACD6 /* PBXContainerItemProxy */; + }; FA456C4D26BDCC9400B83C20 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = shaders_metal; @@ -5027,6 +5165,62 @@ }; name = Release; }; + ED46DDE32D098A0C007CACD6 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 9Z6432XD7L; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = OMapsWidgetExtension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = OMapsWidgetExtension; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Organic Maps. All rights reserved."; + IPHONEOS_DEPLOYMENT_TARGET = 16.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + PRODUCT_BUNDLE_IDENTIFIER = app.organicmaps.debug.OMapsWidgetExtension; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + ED46DDE42D098A0C007CACD6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 9Z6432XD7L; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = OMapsWidgetExtension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = OMapsWidgetExtension; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 Organic Maps. All rights reserved."; + IPHONEOS_DEPLOYMENT_TARGET = 16.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = app.organicmaps.debug.OMapsWidgetExtension; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; FAAB411B149BA84700C245B1 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 347526FA1DC0B00F00918CF5 /* common-debug.xcconfig */; @@ -5135,6 +5329,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; + ED46DDE62D098A0C007CACD6 /* Build configuration list for PBXNativeTarget "OMapsWidgetExtensionExtension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + ED46DDE32D098A0C007CACD6 /* Debug */, + ED46DDE42D098A0C007CACD6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; /* End XCConfigurationList section */ }; rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; diff --git a/iphone/Maps/OMapsWidgetExtension/Assets.xcassets/AccentColor.colorset/Contents.json b/iphone/Maps/OMapsWidgetExtension/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000000..eb87897008 --- /dev/null +++ b/iphone/Maps/OMapsWidgetExtension/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iphone/Maps/OMapsWidgetExtension/Assets.xcassets/AppIcon.appiconset/Contents.json b/iphone/Maps/OMapsWidgetExtension/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..2305880107 --- /dev/null +++ b/iphone/Maps/OMapsWidgetExtension/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,35 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iphone/Maps/OMapsWidgetExtension/Assets.xcassets/Contents.json b/iphone/Maps/OMapsWidgetExtension/Assets.xcassets/Contents.json new file mode 100644 index 0000000000..73c00596a7 --- /dev/null +++ b/iphone/Maps/OMapsWidgetExtension/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iphone/Maps/OMapsWidgetExtension/Assets.xcassets/WidgetBackground.colorset/Contents.json b/iphone/Maps/OMapsWidgetExtension/Assets.xcassets/WidgetBackground.colorset/Contents.json new file mode 100644 index 0000000000..eb87897008 --- /dev/null +++ b/iphone/Maps/OMapsWidgetExtension/Assets.xcassets/WidgetBackground.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iphone/Maps/OMapsWidgetExtension/Assets.xcassets/logo.imageset/Contents.json b/iphone/Maps/OMapsWidgetExtension/Assets.xcassets/logo.imageset/Contents.json new file mode 100644 index 0000000000..7c58c478f6 --- /dev/null +++ b/iphone/Maps/OMapsWidgetExtension/Assets.xcassets/logo.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "logo.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iphone/Maps/OMapsWidgetExtension/Assets.xcassets/logo.imageset/logo.png b/iphone/Maps/OMapsWidgetExtension/Assets.xcassets/logo.imageset/logo.png new file mode 100644 index 0000000000..5c17369efc Binary files /dev/null and b/iphone/Maps/OMapsWidgetExtension/Assets.xcassets/logo.imageset/logo.png differ diff --git a/iphone/Maps/OMapsWidgetExtension/Info.plist b/iphone/Maps/OMapsWidgetExtension/Info.plist new file mode 100644 index 0000000000..0f118fb75e --- /dev/null +++ b/iphone/Maps/OMapsWidgetExtension/Info.plist @@ -0,0 +1,11 @@ + + + + + NSExtension + + NSExtensionPointIdentifier + com.apple.widgetkit-extension + + + diff --git a/iphone/Maps/OMapsWidgetExtension/LiveActivity/AppLogo.swift b/iphone/Maps/OMapsWidgetExtension/LiveActivity/AppLogo.swift new file mode 100644 index 0000000000..bbd87296d4 --- /dev/null +++ b/iphone/Maps/OMapsWidgetExtension/LiveActivity/AppLogo.swift @@ -0,0 +1,9 @@ +import SwiftUI + +struct AppLogo: View { + var body: some View { + Image(.logo) + .resizable() + .aspectRatio(contentMode: .fit) + } +} diff --git a/iphone/Maps/OMapsWidgetExtension/LiveActivity/LiveActivityManager.swift b/iphone/Maps/OMapsWidgetExtension/LiveActivity/LiveActivityManager.swift new file mode 100644 index 0000000000..85d6e5f925 --- /dev/null +++ b/iphone/Maps/OMapsWidgetExtension/LiveActivity/LiveActivityManager.swift @@ -0,0 +1,26 @@ +import ActivityKit +import SwiftUI + +@available(iOS 16.2, *) +final class LiveActivityManager { + static func startActivity(_ attributes: T, content: ActivityContent) throws -> Activity { + return try Activity.request(attributes: attributes, content: content, pushType: nil) + } + + static func update(_ activity: Activity, content: ActivityContent) { + Task { + await activity.update(content) + } + } + + static func stop(_ activity: Activity) { + // semaphore is used for removing the activity during the app termination + let semaphore = DispatchSemaphore(value: 0) + Task { + await activity.end(nil, dismissalPolicy: .immediate) + semaphore.signal() + } + semaphore.wait() + } +} + diff --git a/iphone/Maps/OMapsWidgetExtension/LiveActivity/StatisticDetailView.swift b/iphone/Maps/OMapsWidgetExtension/LiveActivity/StatisticDetailView.swift new file mode 100644 index 0000000000..65731c6e00 --- /dev/null +++ b/iphone/Maps/OMapsWidgetExtension/LiveActivity/StatisticDetailView.swift @@ -0,0 +1,28 @@ +import SwiftUI + +struct StatisticDetailView: View { + private let title: String + private let subtitle: String + + init(title: String, subtitle: String) { + self.title = title + self.subtitle = subtitle + } + + var body: some View { + VStack(alignment: .leading) { + Text(title) + .contentTransition(.numericText()) + .font(.system(size: 14, weight: .bold).monospacedDigit()) + .minimumScaleFactor(0.5) + .lineLimit(1) + .foregroundStyle(.white) + Text(subtitle) + .font(.system(size: 10)) + .minimumScaleFactor(0.5) + .lineLimit(2) + .multilineTextAlignment(.center) + .foregroundStyle(.white) + } + } +} diff --git a/iphone/Maps/OMapsWidgetExtension/LiveActivity/StatisticValueView.swift b/iphone/Maps/OMapsWidgetExtension/LiveActivity/StatisticValueView.swift new file mode 100644 index 0000000000..17ce6c229c --- /dev/null +++ b/iphone/Maps/OMapsWidgetExtension/LiveActivity/StatisticValueView.swift @@ -0,0 +1,17 @@ +import SwiftUI + +struct StatisticValueView: View { + private let value: String + + init(_ value: String) { + self.value = value + } + + var body: some View { + Text(value) + .contentTransition(.numericText()) + .minimumScaleFactor(0.1) + .font(.title3.bold().monospacedDigit()) + .foregroundStyle(.white) + } +} diff --git a/iphone/Maps/OMapsWidgetExtension/LiveActivity/TrackRecordingLiveActivityAttributes.swift b/iphone/Maps/OMapsWidgetExtension/LiveActivity/TrackRecordingLiveActivityAttributes.swift new file mode 100644 index 0000000000..107365a653 --- /dev/null +++ b/iphone/Maps/OMapsWidgetExtension/LiveActivity/TrackRecordingLiveActivityAttributes.swift @@ -0,0 +1,17 @@ +import ActivityKit +import AppIntents + +struct TrackRecordingLiveActivityAttributes: ActivityAttributes { + struct ContentState: Codable, Hashable { + struct StatisticsViewModel: Codable, Hashable { + let key: String + let value: String + } + let duration: StatisticsViewModel + let distance: StatisticsViewModel + let ascent: StatisticsViewModel + let descent: StatisticsViewModel + let maxElevation: StatisticsViewModel + let minElevation: StatisticsViewModel + } +} diff --git a/iphone/Maps/OMapsWidgetExtension/LiveActivity/TrackRecordingLiveActivityConfiguration.swift b/iphone/Maps/OMapsWidgetExtension/LiveActivity/TrackRecordingLiveActivityConfiguration.swift new file mode 100644 index 0000000000..54fda890e1 --- /dev/null +++ b/iphone/Maps/OMapsWidgetExtension/LiveActivity/TrackRecordingLiveActivityConfiguration.swift @@ -0,0 +1,26 @@ +import WidgetKit +import SwiftUI + +struct TrackRecordingLiveActivityConfiguration: Widget { + @Environment(\.colorScheme) private var colorScheme + + var body: some WidgetConfiguration { + ActivityConfiguration(for: TrackRecordingLiveActivityAttributes.self) { context in + TrackRecordingLiveActivityView(state: context.state) + } dynamicIsland: { context in + DynamicIsland { + DynamicIslandExpandedRegion(.center) { + // TODO: Implement the expanded view + } + } compactLeading: { + AppLogo() + } compactTrailing: { + StatisticValueView(context.state.duration.value) + } minimal: { + // TODO: Implement the minimal view + } + } + } +} + + diff --git a/iphone/Maps/OMapsWidgetExtension/LiveActivity/TrackRecordingLiveActivityView.swift b/iphone/Maps/OMapsWidgetExtension/LiveActivity/TrackRecordingLiveActivityView.swift new file mode 100644 index 0000000000..e1d5bbaa08 --- /dev/null +++ b/iphone/Maps/OMapsWidgetExtension/LiveActivity/TrackRecordingLiveActivityView.swift @@ -0,0 +1,71 @@ +import SwiftUI +import WidgetKit + +#if canImport(ActivityKit) + +struct TrackRecordingLiveActivityView: View { + let state: TrackRecordingLiveActivityAttributes.ContentState + + var body: some View { + VStack(alignment: .leading, spacing: 12) { + HStack(alignment: .top, spacing: 24) { + StatisticValueView(state.duration.value) + StatisticValueView(state.distance.value) + Spacer() + AppLogo() + .frame(width: 20, height: 20) + } + .padding([.top, .leading, .trailing], 16) + HStack(alignment: .top, spacing: 20) { + StatisticDetailView(title: state.ascent.value, subtitle: state.ascent.key) + StatisticDetailView(title: state.descent.value, subtitle: state.descent.key) + StatisticDetailView(title: state.maxElevation.value, subtitle: state.maxElevation.key) + StatisticDetailView(title: state.minElevation.value, subtitle: state.minElevation.key) + } + .padding([.leading, .trailing, .bottom], 16) + } + .background(.primary.opacity(0.15)) + } +} + +#if DEBUG +struct TrackRecordingLiveActivityWidget_Previews: PreviewProvider { + static var previews: some View { + Group { + let activityAttributes = TrackRecordingLiveActivityAttributes() + let activityState = TrackRecordingLiveActivityAttributes.ContentState( + duration: .init( + key: "Duration", + value: "1h 12min" + ), + distance: .init( + key: "Distance", + value: "12 km" + ), + ascent: .init( + key: "Ascent", + value: "100 m" + ), + descent: .init( + key: "Descent", + value: "100 m" + ), + maxElevation: .init( + key: "Max Elevation", + value: "100 m" + ), + minElevation: .init( + key: "Min Elevation", + value: "10 m" + ) + ) + + activityAttributes + .previewContext(activityState, viewKind: .content) + .previewDisplayName("Notification") + } + } +} +#endif + +#endif diff --git a/iphone/Maps/OMapsWidgetExtension/OMapsWidgetExtensionBundle.swift b/iphone/Maps/OMapsWidgetExtension/OMapsWidgetExtensionBundle.swift new file mode 100644 index 0000000000..5f85ff1b13 --- /dev/null +++ b/iphone/Maps/OMapsWidgetExtension/OMapsWidgetExtensionBundle.swift @@ -0,0 +1,9 @@ +import WidgetKit +import SwiftUI + +@main +struct OMapsWidgetExtensionBundle: WidgetBundle { + var body: some Widget { + TrackRecordingLiveActivityConfiguration() + } +}