Adding native macOS run destination

This commit is contained in:
Selim Mustafaev 2025-04-30 16:54:11 +03:00
parent 022bfd3307
commit bbaef15acb
57 changed files with 321 additions and 377 deletions

View File

@ -13,7 +13,6 @@
7A06E0B52C707E2B005731AC /* SettingsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A06E0B42C707E2B005731AC /* SettingsService.swift */; };
7A10226C2C551EC500B84627 /* LocationEditScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A10226B2C551EC500B84627 /* LocationEditScreen.swift */; };
7A10226E2C551EE000B84627 /* LocationEditViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A10226D2C551EE000B84627 /* LocationEditViewModel.swift */; };
7A1022722C554A1300B84627 /* CustomHostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1022712C554A1300B84627 /* CustomHostingController.swift */; };
7A1022772C557EC400B84627 /* LocationPickerScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1022762C557EC400B84627 /* LocationPickerScreen.swift */; };
7A1022792C557ED600B84627 /* LocationPickerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1022782C557ED600B84627 /* LocationPickerViewModel.swift */; };
7A11470A23FDE7E600B424AF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A11470923FDE7E600B424AF /* Assets.xcassets */; };
@ -98,6 +97,9 @@
7A809F392D66755B00CF1B3C /* Error+Canceled.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A809F382D66755B00CF1B3C /* Error+Canceled.swift */; };
7A8AB76525A0DB8F00ECF2C1 /* BundleVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8AB76425A0DB8F00ECF2C1 /* BundleVersion.swift */; };
7A912F372D381B7400002938 /* LicensePlateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A912F362D381B7400002938 /* LicensePlateView.swift */; };
7A91CE952DC2422B00DBA953 /* HideTabBarModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A91CE942DC2422B00DBA953 /* HideTabBarModifier.swift */; };
7A91CE982DC243AD00DBA953 /* TitleModeInlineModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A91CE972DC243AD00DBA953 /* TitleModeInlineModifier.swift */; };
7A91CE9A2DC2470F00DBA953 /* TextFieldDumbModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A91CE992DC2470F00DBA953 /* TextFieldDumbModifier.swift */; };
7A9519792D80B3E800E69883 /* AudioRecordService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9519782D80B3E800E69883 /* AudioRecordService.swift */; };
7A95197B2D80B41600E69883 /* AudioRecordServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A95197A2D80B41600E69883 /* AudioRecordServiceProtocol.swift */; };
7A95197D2D80B43D00E69883 /* AudioRecordError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A95197C2D80B43D00E69883 /* AudioRecordError.swift */; };
@ -110,11 +112,9 @@
7AA515D02D9ABCC800EB3418 /* RecordPlayerService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA515CF2D9ABCC800EB3418 /* RecordPlayerService.swift */; };
7AA515D22D9ABCE600EB3418 /* RecordPlayerServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA515D12D9ABCE600EB3418 /* RecordPlayerServiceProtocol.swift */; };
7AA515DA2D9ADEF000EB3418 /* StorageError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA515D92D9ADEF000EB3418 /* StorageError.swift */; };
7AA7BC3525A5DFB80053A5D5 /* ExceptionCatcher in Frameworks */ = {isa = PBXBuildFile; productRef = 7A813DC02508C4D900CC93B9 /* ExceptionCatcher */; };
7AA7BC3625A5DFB80053A5D5 /* PKHUD in Frameworks */ = {isa = PBXBuildFile; productRef = 7AABDE1C2532F3EB0041AFC6 /* PKHUD */; };
7AAAFAD32C4D0FD00050410D /* ACImageSliderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AAAFAD22C4D0FD00050410D /* ACImageSliderView.swift */; };
7AAAFAD32C4D0FD00050410D /* ACImageSliderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AAAFAD22C4D0FD00050410D /* ACImageSliderView.swift */; platformFilter = ios; };
7AAAFADA2C4D1AFE0050410D /* Zoomable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AAAFAD92C4D1AFE0050410D /* Zoomable.swift */; };
7AAAFADC2C4D1E130050410D /* ACImageSliderView+Modifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AAAFADB2C4D1E130050410D /* ACImageSliderView+Modifier.swift */; };
7AAAFADC2C4D1E130050410D /* ACImageSliderView+Modifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AAAFADB2C4D1E130050410D /* ACImageSliderView+Modifier.swift */; platformFilter = ios; };
7AAAFADE2C4D23620050410D /* ACImageSliderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AAAFADD2C4D23620050410D /* ACImageSliderModel.swift */; };
7AABB1F2267E9CC800D7AB32 /* SwiftDate in Frameworks */ = {isa = PBXBuildFile; productRef = 7AABB1F1267E9CC800D7AB32 /* SwiftDate */; };
7AABBE3B2CF9F85600346588 /* Binding+Map.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AABBE3A2CF9F85600346588 /* Binding+Map.swift */; };
@ -142,7 +142,6 @@
7ABDA80B2D8715DC0083C715 /* VehicleRecordError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ABDA80A2D8715DC0083C715 /* VehicleRecordError.swift */; };
7ABDA80D2D8721B10083C715 /* Substrings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ABDA80C2D8721B10083C715 /* Substrings.swift */; };
7ABDA80F2D8723F90083C715 /* StorageService+AudioRecords.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ABDA80E2D8723F90083C715 /* StorageService+AudioRecords.swift */; };
7AC3554A2969652F00889457 /* SwiftEntryKit in Frameworks */ = {isa = PBXBuildFile; productRef = 7AC355492969652F00889457 /* SwiftEntryKit */; };
7AC44B822DB390B900ADC026 /* MainTabScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AC44B812DB390B900ADC026 /* MainTabScreen.swift */; };
7AC44B8A2DB4395300ADC026 /* SearchSplitScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AC44B892DB4395300ADC026 /* SearchSplitScreen.swift */; };
7AC8B2762D6A01C700190706 /* UISearchTextField+Dumb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AC8B2752D6A01C700190706 /* UISearchTextField+Dumb.swift */; };
@ -249,7 +248,6 @@
7A06E0B42C707E2B005731AC /* SettingsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsService.swift; sourceTree = "<group>"; };
7A10226B2C551EC500B84627 /* LocationEditScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationEditScreen.swift; sourceTree = "<group>"; };
7A10226D2C551EE000B84627 /* LocationEditViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationEditViewModel.swift; sourceTree = "<group>"; };
7A1022712C554A1300B84627 /* CustomHostingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomHostingController.swift; sourceTree = "<group>"; };
7A1022762C557EC400B84627 /* LocationPickerScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationPickerScreen.swift; sourceTree = "<group>"; };
7A1022782C557ED600B84627 /* LocationPickerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationPickerViewModel.swift; sourceTree = "<group>"; };
7A1146FD23FDE7E500B424AF /* AutoCat.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AutoCat.app; sourceTree = BUILT_PRODUCTS_DIR; };
@ -344,6 +342,9 @@
7A8AB76425A0DB8F00ECF2C1 /* BundleVersion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BundleVersion.swift; sourceTree = "<group>"; };
7A8AB76725A0DC8200ECF2C1 /* DebugInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugInfo.swift; sourceTree = "<group>"; };
7A912F362D381B7400002938 /* LicensePlateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LicensePlateView.swift; sourceTree = "<group>"; };
7A91CE942DC2422B00DBA953 /* HideTabBarModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HideTabBarModifier.swift; sourceTree = "<group>"; };
7A91CE972DC243AD00DBA953 /* TitleModeInlineModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleModeInlineModifier.swift; sourceTree = "<group>"; };
7A91CE992DC2470F00DBA953 /* TextFieldDumbModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFieldDumbModifier.swift; sourceTree = "<group>"; };
7A92D0AB240425B100EF3B77 /* ATGMediaBrowser.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ATGMediaBrowser.framework; path = Carthage/Build/iOS/ATGMediaBrowser.framework; sourceTree = "<group>"; };
7A9519782D80B3E800E69883 /* AudioRecordService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRecordService.swift; sourceTree = "<group>"; };
7A95197A2D80B41600E69883 /* AudioRecordServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRecordServiceProtocol.swift; sourceTree = "<group>"; };
@ -443,12 +444,9 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
7AA7BC3525A5DFB80053A5D5 /* ExceptionCatcher in Frameworks */,
7AA7BC3625A5DFB80053A5D5 /* PKHUD in Frameworks */,
7A386A4B2DAC35F10051676A /* ClusterMap in Frameworks */,
7A7AA2CA2DA2C85100276D83 /* RealmSwift in Frameworks */,
7A386A4D2DAC35F10051676A /* ClusterMapSwiftUI in Frameworks */,
7AC3554A2969652F00889457 /* SwiftEntryKit in Frameworks */,
7ACBB91E2CB9B155005A5168 /* Mockable in Frameworks */,
7AF6D2042677C03B0086EA64 /* AutoCatCore.framework in Frameworks */,
7A96AE2F246B2BCD00297C33 /* WebKit.framework in Frameworks */,
@ -851,6 +849,16 @@
path = ThirdParty;
sourceTree = "<group>";
};
7A91CE962DC2436D00DBA953 /* Modifiers */ = {
isa = PBXGroup;
children = (
7A91CE942DC2422B00DBA953 /* HideTabBarModifier.swift */,
7A91CE972DC243AD00DBA953 /* TitleModeInlineModifier.swift */,
7A91CE992DC2470F00DBA953 /* TextFieldDumbModifier.swift */,
);
path = Modifiers;
sourceTree = "<group>";
};
7A9519772D80B3B200E69883 /* AudioRecordService */ = {
isa = PBXGroup;
children = (
@ -1045,13 +1053,13 @@
7AFBE8C52C30812E003C491D /* SwiftUI */ = {
isa = PBXGroup;
children = (
7A91CE962DC2436D00DBA953 /* Modifiers */,
7AD176AE2DC127290023049D /* NumberEditView */,
7AAAFAD12C4D0FB00050410D /* ACImageSlider */,
7AFBE8C62C30814E003C491D /* ACProgressHud */,
7A961C6B2C4C3C8600CE2211 /* TextRowView.swift */,
7A961C6D2C4C3C9E00CE2211 /* LinkRowView.swift */,
7AAAFAD92C4D1AFE0050410D /* Zoomable.swift */,
7A1022712C554A1300B84627 /* CustomHostingController.swift */,
7A5D7E0B2C71EB25002C17E7 /* ToggleRowView.swift */,
7AF8606F2CBAA24500954D2F /* NavigationLink.swift */,
7A2E11282CCE395300E5CA17 /* OptionalDatePicker.swift */,
@ -1106,9 +1114,6 @@
);
name = AutoCat;
packageProductDependencies = (
7A813DC02508C4D900CC93B9 /* ExceptionCatcher */,
7AABDE1C2532F3EB0041AFC6 /* PKHUD */,
7AC355492969652F00889457 /* SwiftEntryKit */,
7ACBB91D2CB9B155005A5168 /* Mockable */,
7A7AA2C92DA2C85100276D83 /* RealmSwift */,
7A386A4A2DAC35F10051676A /* ClusterMap */,
@ -1229,9 +1234,6 @@
mainGroup = 7A1146F423FDE7E500B424AF;
packageReferences = (
7A05160F241412CA00FC55AC /* XCRemoteSwiftPackageReference "SwiftDate" */,
7A813DBF2508C4D900CC93B9 /* XCRemoteSwiftPackageReference "ExceptionCatcher" */,
7AABDE1B2532F3EB0041AFC6 /* XCRemoteSwiftPackageReference "PKHUD" */,
7AC355482969652F00889457 /* XCRemoteSwiftPackageReference "SwiftEntryKit" */,
7A1CF7FD29A41C2F007962DA /* XCRemoteSwiftPackageReference "realm-swift" */,
7A6C4D9C2C56BCA600982597 /* XCRemoteSwiftPackageReference "SwiftLocation" */,
7ACBB91C2CB9B155005A5168 /* XCRemoteSwiftPackageReference "Mockable" */,
@ -1316,6 +1318,7 @@
7A6C65222D999325001240C2 /* AudioRecordViewModel.swift in Sources */,
7A06E0AE2C7065C7005731AC /* SettingsViewModel.swift in Sources */,
7AB4E42C2D397D8E0006D052 /* VehicleCellView.swift in Sources */,
7A91CE9A2DC2470F00DBA953 /* TextFieldDumbModifier.swift in Sources */,
7A961C6E2C4C3C9E00CE2211 /* LinkRowView.swift in Sources */,
7ADF6CA12512244400F237B2 /* MapExt.swift in Sources */,
7AC44B822DB390B900ADC026 /* MainTabScreen.swift in Sources */,
@ -1338,7 +1341,6 @@
7A7DADAC2D99738300F52F6C /* AudioRecordView.swift in Sources */,
7AB9FE2A2D08CF35005DE374 /* EventsScreenMode.swift in Sources */,
7AB490292D6B1217002F39C6 /* ACKeyboardView.swift in Sources */,
7A1022722C554A1300B84627 /* CustomHostingController.swift in Sources */,
7A1022792C557ED600B84627 /* LocationPickerViewModel.swift in Sources */,
7AF231932DA1C28100AE5EB3 /* AuthScreen.swift in Sources */,
7A1E78F82CE900440004B740 /* ReportViewModel.swift in Sources */,
@ -1354,6 +1356,7 @@
7AFBE8C42C302561003C491D /* ACHudContainer.swift in Sources */,
7A06E0AC2C7065AC005731AC /* SettingsScreen.swift in Sources */,
7AF231992DA27C1B00AE5EB3 /* ACButtonView.swift in Sources */,
7A91CE952DC2422B00DBA953 /* HideTabBarModifier.swift in Sources */,
7A7158002C43EA6900852088 /* OwnersScreen.swift in Sources */,
7A4955822D58CCF900912E66 /* HistoryFilter.swift in Sources */,
7A4322912CB2CC8A00085CF6 /* FiltersScreen.swift in Sources */,
@ -1366,6 +1369,7 @@
7AB9FE222D08C2A5005DE374 /* EventsScreen.swift in Sources */,
7A5911F02D63266B00EC51BA /* SearchViewModel.swift in Sources */,
7A589E0F2D6B6E8E00EF3FBE /* NumberEditView.swift in Sources */,
7A91CE982DC243AD00DBA953 /* TitleModeInlineModifier.swift in Sources */,
7A9519802D80B6C100E69883 /* RecordsScreen.swift in Sources */,
7A131FD52D37B76A00DC7755 /* HistoryViewModel.swift in Sources */,
);
@ -1659,7 +1663,9 @@
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTS_MACCATALYST = YES;
REGISTER_APP_GROUPS = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
@ -1686,7 +1692,9 @@
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTS_MACCATALYST = YES;
REGISTER_APP_GROUPS = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
@ -1821,7 +1829,11 @@
MACOSX_DEPLOYMENT_TARGET = 14.6;
PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCatCore;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
REGISTER_APP_GROUPS = YES;
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG MOCKING";
SWIFT_UPCOMING_FEATURE_DISABLE_OUTWARD_ACTOR_ISOLATION = YES;
SWIFT_VERSION = 6.0;
@ -1853,7 +1865,11 @@
MACOSX_DEPLOYMENT_TARGET = 14.6;
PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCatCore;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
REGISTER_APP_GROUPS = YES;
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_UPCOMING_FEATURE_DISABLE_OUTWARD_ACTOR_ISOLATION = YES;
SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
@ -1945,30 +1961,6 @@
minimumVersion = 6.0.0;
};
};
7A813DBF2508C4D900CC93B9 /* XCRemoteSwiftPackageReference "ExceptionCatcher" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/sindresorhus/ExceptionCatcher";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 1.1.0;
};
};
7AABDE1B2532F3EB0041AFC6 /* XCRemoteSwiftPackageReference "PKHUD" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/pkluz/PKHUD.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 5.4.0;
};
};
7AC355482969652F00889457 /* XCRemoteSwiftPackageReference "SwiftEntryKit" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/huri000/SwiftEntryKit";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 2.0.0;
};
};
7ACBB91C2CB9B155005A5168 /* XCRemoteSwiftPackageReference "Mockable" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/Kolos65/Mockable";
@ -2005,31 +1997,16 @@
package = 7A1CF7FD29A41C2F007962DA /* XCRemoteSwiftPackageReference "realm-swift" */;
productName = RealmSwift;
};
7A813DC02508C4D900CC93B9 /* ExceptionCatcher */ = {
isa = XCSwiftPackageProductDependency;
package = 7A813DBF2508C4D900CC93B9 /* XCRemoteSwiftPackageReference "ExceptionCatcher" */;
productName = ExceptionCatcher;
};
7AABB1F1267E9CC800D7AB32 /* SwiftDate */ = {
isa = XCSwiftPackageProductDependency;
package = 7A05160F241412CA00FC55AC /* XCRemoteSwiftPackageReference "SwiftDate" */;
productName = SwiftDate;
};
7AABDE1C2532F3EB0041AFC6 /* PKHUD */ = {
isa = XCSwiftPackageProductDependency;
package = 7AABDE1B2532F3EB0041AFC6 /* XCRemoteSwiftPackageReference "PKHUD" */;
productName = PKHUD;
};
7AB5871C2C42C1CF00FA7B66 /* RealmSwift */ = {
isa = XCSwiftPackageProductDependency;
package = 7A1CF7FD29A41C2F007962DA /* XCRemoteSwiftPackageReference "realm-swift" */;
productName = RealmSwift;
};
7AC355492969652F00889457 /* SwiftEntryKit */ = {
isa = XCSwiftPackageProductDependency;
package = 7AC355482969652F00889457 /* XCRemoteSwiftPackageReference "SwiftEntryKit" */;
productName = SwiftEntryKit;
};
7ACBB91D2CB9B155005A5168 /* Mockable */ = {
isa = XCSwiftPackageProductDependency;
package = 7ACBB91C2CB9B155005A5168 /* XCRemoteSwiftPackageReference "Mockable" */;

View File

@ -1,5 +1,5 @@
{
"originHash" : "9a7838ec160dde976fc2028176dc43038769553e6d8eb4d7d117f851f899baaf",
"originHash" : "b26032c73d0741690e860809b31156025c85a200a7d53a64391683433e6a82a4",
"pins" : [
{
"identity" : "clustermap",
@ -10,15 +10,6 @@
"version" : "2.1.1"
}
},
{
"identity" : "exceptioncatcher",
"kind" : "remoteSourceControl",
"location" : "https://github.com/sindresorhus/ExceptionCatcher",
"state" : {
"revision" : "3787f25119e1406b4c5e47fc654626a9d5d7e111",
"version" : "1.1.0"
}
},
{
"identity" : "mockable",
"kind" : "remoteSourceControl",
@ -28,15 +19,6 @@
"version" : "0.3.1"
}
},
{
"identity" : "pkhud",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pkluz/PKHUD.git",
"state" : {
"revision" : "8fd26f23057c6bebd6695524b1c3e05e93aba571",
"version" : "5.4.0"
}
},
{
"identity" : "realm-core",
"kind" : "remoteSourceControl",
@ -73,15 +55,6 @@
"version" : "6.3.1"
}
},
{
"identity" : "swiftentrykit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/huri000/SwiftEntryKit",
"state" : {
"revision" : "5ad36cccf0c4b9fea32f4e9b17a8e38f07563ef0",
"version" : "2.0.0"
}
},
{
"identity" : "swiftlocation",
"kind" : "remoteSourceControl",

View File

@ -0,0 +1,34 @@
{
"colors" : [
{
"color" : {
"color-space" : "extended-gray",
"components" : {
"alpha" : "1.000",
"white" : "124"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "extended-gray",
"components" : {
"alpha" : "1.000",
"white" : "81"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -1,6 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}

View File

@ -1,6 +0,0 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -1,25 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "check-37.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "check-54.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 967 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,25 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "check-51.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "check-75.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -1,25 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "record-47.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "record-69.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 924 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,25 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "record-63.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "record-93.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,25 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "search-35.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "search-51.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 870 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -1,25 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "search-47.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "search-69.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -1,25 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "settings-37.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "settings-54.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1,25 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "settings-51.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "settings-75.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -37,7 +37,7 @@ struct AutoCatApp: App {
@ViewBuilder
var mainScreen: some View {
if UIDevice.isIPhone {
if Device.isIPhone {
MainTabScreen()
} else {
MainSplitScreen()

View File

@ -6,12 +6,19 @@
// Copyright © 2025 Selim Mustafaev. All rights reserved.
//
#if canImport(UIKit)
import UIKit
#endif
extension UIDevice {
@MainActor
struct Device {
static var isIPhone: Bool {
current.userInterfaceIdiom == .phone
#if os(macOS)
false
#else
UIDevice.current.userInterfaceIdiom == .phone
#endif
}
}

View File

@ -45,7 +45,9 @@ struct AdsScreen: View {
}
}
.navigationTitle("Ads")
#if !os(macOS)
.imageSlider($galleryModel)
#endif
}
func imageGrid(links: [String]) -> some View {

View File

@ -28,11 +28,15 @@ struct AuthScreen: View {
VStack(spacing: 16) {
Group {
TextField("Email", text: $viewModel.email, prompt: Text("Email"))
#if !os(macOS)
.keyboardType(.emailAddress)
#endif
SecureField("Password", text: $viewModel.password, prompt: Text("Password"))
}
.disableAutocorrection(true)
#if !os(macOS)
.autocapitalization(.none)
#endif
.padding(8)
.background {
RoundedRectangle(cornerRadius: 8)

View File

@ -10,7 +10,7 @@ import SwiftUI
import AutoCatCore
import CoreLocation
import UniformTypeIdentifiers
import MobileCoreServices
//import MobileCoreServices
import MapKit
extension UTType {
@ -42,7 +42,11 @@ class EventsViewModel: ACHudContainer {
var onUpdate: (VehicleDto) -> Void
var isPasteAvailable: Bool {
#if os(macOS)
NSPasteboard.general.data(forType: .init(UTType.vehicleEvent.identifier)) != nil
#else
UIPasteboard.general.data(forPasteboardType: UTType.vehicleEvent.identifier) != nil
#endif
}
var shouldDisplayEventAuthors: Bool {
@ -174,14 +178,26 @@ class EventsViewModel: ACHudContainer {
let items = sharedData.compactMapValues { $0 }
if !items.isEmpty {
#if os(macOS)
NSPasteboard.general.setData(try? JSONEncoder().encode(eventDto), forType: .init(UTType.vehicleEvent.identifier))
if let urlString = getMapLink(for: event)?.absoluteString {
NSPasteboard.general.setString(urlString, forType: .string)
}
#else
UIPasteboard.general.items = [items]
#endif
}
}
func confirmPaste() {
guard let data = UIPasteboard.general.data(forPasteboardType: UTType.vehicleEvent.identifier),
var eventDto = try? JSONDecoder().decode(VehicleEventDto.self, from: data)
else {
#if os(macOS)
let data = NSPasteboard.general.data(forType: .init(UTType.vehicleEvent.identifier))
#else
let data = UIPasteboard.general.data(forPasteboardType: UTType.vehicleEvent.identifier)
#endif
guard let data, var eventDto = try? JSONDecoder().decode(VehicleEventDto.self, from: data) else {
return
}
@ -202,13 +218,22 @@ class EventsViewModel: ACHudContainer {
return
}
#if os(macOS)
openInMaps(event)
#else
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url)
} else {
let placemark = MKPlacemark(coordinate: event.coordinate)
let mapItem = MKMapItem(placemark: placemark)
mapItem.name = event.date
mapItem.openInMaps()
openInMaps(event)
}
#endif
}
func openInMaps(_ event: EventModel) {
let placemark = MKPlacemark(coordinate: event.coordinate)
let mapItem = MKMapItem(placemark: placemark)
mapItem.name = event.date
mapItem.openInMaps()
}
}

View File

@ -51,7 +51,7 @@ struct FiltersScreen: View {
ForEach(viewModel.years, id: \.self) { Text($0.text) }
}
}
.pickerStyle(.navigationLink)
.pickerStyle(.automatic)
Section {
Picker("Added by", selection: $viewModel.filter.addedBy) {
@ -114,9 +114,9 @@ struct FiltersScreen: View {
}
}
.navigationTitle("Filters")
.navigationBarTitleDisplayMode(.inline)
.titleModeInline()
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
ToolbarItem(placement: .primaryAction) {
Button("Done") {
viewModel.applyFilters()
dismiss()
@ -124,7 +124,7 @@ struct FiltersScreen: View {
}
if horizontalSizeClass == .regular {
ToolbarItem(placement: .topBarLeading) {
ToolbarItem(placement: .cancellationAction) {
Button("Close") {
dismiss()
}
@ -134,6 +134,6 @@ struct FiltersScreen: View {
.task {
await viewModel.loadData()
}
.toolbar(.hidden, for: .tabBar)
.hideTabBar()
}
}

View File

@ -55,7 +55,9 @@ struct GalleryScreen: View {
}
}
}
#if !os(macOS)
.imageSlider($galleryModel)
#endif
}
var columns: [GridItem] {

View File

@ -9,25 +9,57 @@
import WebKit
import SwiftUI
struct WebView: UIViewRepresentable {
class WebViewCoordinator: NSObject, WKNavigationDelegate {
class Coordinator: NSObject, WKNavigationDelegate {
var decidePolicyClosure: ((WKNavigationAction) async -> WKNavigationActionPolicy)?
var decidePolicyClosure: ((WKNavigationAction) async -> WKNavigationActionPolicy)?
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction) async -> WKNavigationActionPolicy {
if let decidePolicyClosure {
return await decidePolicyClosure(navigationAction)
} else {
return .allow
}
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction) async -> WKNavigationActionPolicy {
if let decidePolicyClosure {
return await decidePolicyClosure(navigationAction)
} else {
return .allow
}
}
}
#if os(macOS)
struct WebView: NSViewRepresentable {
let url: URL
let userAgent: String?
@State private var delegate = Coordinator()
@State private var delegate = WebViewCoordinator()
func makeNSView(context: Context) -> WKWebView {
let webView = WKWebView()
webView.navigationDelegate = context.coordinator
return webView
}
func updateNSView(_ webView: WKWebView, context: Context) {
webView.customUserAgent = userAgent
webView.navigationDelegate = context.coordinator
let request = URLRequest(url: url)
webView.load(request)
}
func makeCoordinator() -> WebViewCoordinator {
delegate
}
}
#else
struct WebView: UIViewRepresentable {
let url: URL
let userAgent: String?
@State private var delegate = WebViewCoordinator()
func makeUIView(context: Context) -> WKWebView {
@ -45,11 +77,12 @@ struct WebView: UIViewRepresentable {
webView.load(request)
}
func makeCoordinator() -> Coordinator {
func makeCoordinator() -> WebViewCoordinator {
delegate
}
}
#endif
extension WebView {

View File

@ -26,7 +26,7 @@ struct HistoryScreen: View {
ForEach(viewModel.vehicleSections) { section in
Section(header: Text(section.header)) {
ForEach(section.elements) { vehicle in
if UIDevice.isIPhone {
if Device.isIPhone {
NavigationLink(value: HistoryRoute.localReport(vehicle)) {
vehicleCell(vehicle)
}
@ -42,13 +42,12 @@ struct HistoryScreen: View {
}
.hud($viewModel.hud)
.listStyle(.plain)
.navigationBarTitleDisplayMode(.inline)
.titleModeInline()
.navigationTitle(String.localizedStringWithFormat(NSLocalizedString("vehicles found", comment: ""),
viewModel.vehiclesCount))
.searchable(text: $viewModel.searchText, prompt: "Search plate numbers")
.searchPresentationToolbarBehavior(.avoidHidingContent)
.autocorrectionDisabled()
.textInputAutocapitalization(.never)
.makeTextFieldDumb()
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button("", systemImage: "square.and.arrow.up") {

View File

@ -145,7 +145,7 @@ final class HistoryViewModel: ACHudContainer {
if errors.isEmpty {
hud = nil
if !vehicle.unrecognized {
if UIDevice.isIPhone {
if Device.isIPhone {
Router.shared.openLocalReport(vehicle: vehicle)
} else {
selectedVehicleId = vehicle.id
@ -204,7 +204,7 @@ final class HistoryViewModel: ACHudContainer {
guard let self else { return }
let vehicle = try await apiService.getReport(for: number)
if UIDevice.isIPhone {
if Device.isIPhone {
Router.shared.openSharedReport(vehicle: vehicle)
} else {
vehicleToOpen = vehicle

View File

@ -112,7 +112,7 @@ struct MainSplitScreen: View {
}
}
}
.toolbar(.visible, for: .navigationBar)
//.toolbar(.visible, for: .navigationBar)
}
@ViewBuilder

View File

@ -7,8 +7,6 @@
//
import SwiftUI
import UIKit
import SwiftEntryKit
import AutoCatCore
struct MainTabScreen: View {

View File

@ -40,7 +40,7 @@ struct MapScreen: View {
}
.hud($viewModel.hud)
.navigationTitle(viewModel.title)
.navigationBarTitleDisplayMode(.inline)
.titleModeInline()
.readSize { newValue in
viewModel.mapSize = newValue
}
@ -54,13 +54,13 @@ struct MapScreen: View {
}
.toolbar {
if horizontalSizeClass == .regular {
ToolbarItem(placement: .topBarLeading) {
ToolbarItem(placement: .cancellationAction) {
Button("Close") {
dismiss()
}
}
}
}
.toolbar(.hidden, for: .tabBar)
.hideTabBar()
}
}

View File

@ -50,7 +50,7 @@ struct NotesScreen: View {
}
.listStyle(.inset)
.navigationTitle("Notes")
.navigationBarTitleDisplayMode(.inline)
.titleModeInline()
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button {

View File

@ -8,9 +8,16 @@
import Foundation
import AutoCatCore
import UIKit
import UniformTypeIdentifiers
#if canImport(UIKit)
import UIKit
#endif
#if canImport(AppKit)
import AppKit
#endif
@MainActor
@Observable
class NotesViewModel: ACHudContainer {
@ -89,7 +96,11 @@ class NotesViewModel: ACHudContainer {
func copyNote(_ note: VehicleNoteDto) {
#if !os(macOS)
UIPasteboard.general.setValue(note.text,
forPasteboardType: UTType.plainText.identifier)
#else
NSPasteboard.general.setString(note.text, forType: .string)
#endif
}
}

View File

@ -47,7 +47,7 @@ struct RecordsScreen: View {
.listStyle(.inset)
.hud($viewModel.hud)
.navigationTitle("Voice records")
.navigationBarTitleDisplayMode(.inline)
.titleModeInline()
.onAppear {
Task { await viewModel.onAppear() }
}

View File

@ -148,7 +148,7 @@ struct ReportScreen: View {
GalleryScreen(photos: viewModel.vehicle.photos)
}
}
.toolbar(.hidden, for: .tabBar)
.hideTabBar()
}
@ViewBuilder

View File

@ -35,9 +35,8 @@ struct SearchScreen: View {
.hud($viewModel.hud)
.searchable(text: $viewModel.searchText, prompt: "Search plate numbers")
.searchPresentationToolbarBehavior(.avoidHidingContent)
.disableAutocorrection(true)
.autocapitalization(.none)
.navigationBarTitleDisplayMode(.inline)
.makeTextFieldDumb()
.titleModeInline()
.navigationTitle(String.localizedStringWithFormat(NSLocalizedString("vehicles found", comment: ""),
viewModel.vehiclesCount))
.onAppear {
@ -47,7 +46,7 @@ struct SearchScreen: View {
Task { await viewModel.reloadData() }
}
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
ToolbarItem(placement: .primaryAction) {
toolbarMenu
}
}
@ -68,7 +67,7 @@ struct SearchScreen: View {
ForEach(viewModel.vehicleSections) { section in
Section(header: Text(section.header)) {
ForEach(section.elements) { vehicle in
if UIDevice.isIPhone {
if Device.isIPhone {
NavigationLink(value: vehicle) {
vehicleCell(vehicle)
}

View File

@ -80,7 +80,7 @@ struct SettingsScreen: View {
}
}
.navigationTitle("Settings")
.navigationBarTitleDisplayMode(.inline)
.titleModeInline()
.confirmationDialog(viewModel.googleUsername ?? "",
isPresented: $googleSheetOpened,
titleVisibility: .visible) {

View File

@ -1,27 +0,0 @@
//
// CustomHostingController.swift
// AutoCat
//
// Created by Selim Mustafaev on 27.07.2024.
// Copyright © 2024 Selim Mustafaev. All rights reserved.
//
import UIKit
import SwiftUI
final class CustomHostingController<T: View>: UIHostingController<T> {
var continuation: CheckedContinuation<Void, Never>?
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
if isMovingFromParent || isBeingDismissed {
continuation?.resume()
}
}
func waitForDisappear() async {
await withCheckedContinuation { continuation = $0 }
}
}

View File

@ -0,0 +1,30 @@
//
// HideTabBarModifier.swift
// AutoCat
//
// Created by Selim Mustafaev on 30.04.2025.
// Copyright © 2025 Selim Mustafaev. All rights reserved.
//
import SwiftUI
struct HideTabBarModifier: ViewModifier {
func body(content: Content) -> some View {
#if os(macOS)
content
#else
content
.toolbar(.hidden, for: .tabBar)
#endif
}
}
extension View {
func hideTabBar() -> some View {
modifier(HideTabBarModifier())
}
}

View File

@ -0,0 +1,32 @@
//
// TextFieldDumbModifier.swift
// AutoCat
//
// Created by Selim Mustafaev on 30.04.2025.
// Copyright © 2025 Selim Mustafaev. All rights reserved.
//
import SwiftUI
struct TextFieldDumbModifier: ViewModifier {
func body(content: Content) -> some View {
#if os(macOS)
content
.disableAutocorrection(true)
#else
content
.disableAutocorrection(true)
.autocapitalization(.none)
#endif
}
}
extension View {
func makeTextFieldDumb() -> some View {
modifier(TextFieldDumbModifier())
}
}

View File

@ -0,0 +1,30 @@
//
// TitleModeInlineModifier.swift
// AutoCat
//
// Created by Selim Mustafaev on 30.04.2025.
// Copyright © 2025 Selim Mustafaev. All rights reserved.
//
import SwiftUI
struct TitleModeInlineModifier: ViewModifier {
func body(content: Content) -> some View {
#if os(macOS)
content
#else
content
.navigationBarTitleDisplayMode(.inline)
#endif
}
}
extension View {
func titleModeInline() -> some View {
modifier(TitleModeInlineModifier())
}
}

View File

@ -19,7 +19,6 @@ struct NumberEditView: View {
VStack(spacing: 16) {
Text("Check number")
.font(.headline)
//.padding(.top, 24)
HStack(spacing: 16) {
LicensePlateView(number: number, foreground: .primary)

View File

@ -6,7 +6,15 @@
// Copyright © 2025 Selim Mustafaev. All rights reserved.
//
#if canImport(UIKit)
import UIKit
#endif
#if canImport(AppKit)
import AppKit
#endif
#if !os(macOS)
extension UISearchTextField {
@ -22,3 +30,5 @@ extension UISearchTextField {
}
}
}
#endif

View File

@ -61,9 +61,9 @@ struct VehicleCellView: View {
func getForegroundColor() -> Color {
if vehicle.unrecognized {
Color(UIColor.systemRed)
.red
} else if vehicle.outdated {
Color(UIColor.systemGray3)
Color("PlateForegroundGray")
} else {
Color("PlateForeground")
}

View File

@ -66,8 +66,10 @@ extension AudioRecordService: AudioRecordServiceProtocol {
throw AudioRecordError.unknown
}
#if !os(macOS)
try AVAudioSession.sharedInstance().setCategory(.playAndRecord)
try AVAudioSession.sharedInstance().setActive(true)
#endif
recorder = try AVAudioRecorder(url: url, settings: audioFileSettings)
recorder?.record()

View File

@ -33,11 +33,14 @@ public final class RecordPlayerService: NSObject {
activateProgressTimer()
self.onProgress = onProgress
#if !os(macOS)
try activateSession()
#endif
player?.play()
}
#if !os(macOS)
func activateSession() throws {
try AVAudioSession.sharedInstance().setCategory(
.playback,
@ -53,6 +56,7 @@ public final class RecordPlayerService: NSObject {
options: .notifyOthersOnDeactivation
)
}
#endif
func activateProgressTimer() {
@ -87,9 +91,13 @@ extension RecordPlayerService: RecordPlayerServiceProtocol {
if player.isPlaying {
player.pause()
deactivateProgressTimer()
#if !os(macOS)
try deactivateSession()
#endif
} else {
#if !os(macOS)
try activateSession()
#endif
activateProgressTimer()
player.play()
}
@ -131,6 +139,8 @@ extension RecordPlayerService: AVAudioPlayerDelegate {
record = nil
deactivateProgressTimer()
#if !os(macOS)
try? deactivateSession()
#endif
}
}