Removing SwiftJWT with all its dependencies (along with some audio playing/recording code adjustments)
This commit is contained in:
parent
f513222d72
commit
55e3a3008e
@ -28,7 +28,6 @@
|
|||||||
7A11472323FEA18700B424AF /* RxBlocking in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11472223FEA18700B424AF /* RxBlocking */; };
|
7A11472323FEA18700B424AF /* RxBlocking in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11472223FEA18700B424AF /* RxBlocking */; };
|
||||||
7A11472623FEA1F400B424AF /* Realm in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11472523FEA1F400B424AF /* Realm */; };
|
7A11472623FEA1F400B424AF /* Realm in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11472523FEA1F400B424AF /* Realm */; };
|
||||||
7A11472823FEA1F400B424AF /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11472723FEA1F400B424AF /* RealmSwift */; };
|
7A11472823FEA1F400B424AF /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11472723FEA1F400B424AF /* RealmSwift */; };
|
||||||
7A11472B23FEA24D00B424AF /* Action in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11472A23FEA24D00B424AF /* Action */; };
|
|
||||||
7A11474423FF06CA00B424AF /* Api.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11474323FF06CA00B424AF /* Api.swift */; };
|
7A11474423FF06CA00B424AF /* Api.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11474323FF06CA00B424AF /* Api.swift */; };
|
||||||
7A11474723FF2AA500B424AF /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11474623FF2AA500B424AF /* User.swift */; };
|
7A11474723FF2AA500B424AF /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11474623FF2AA500B424AF /* User.swift */; };
|
||||||
7A11474923FF2B2D00B424AF /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11474823FF2B2D00B424AF /* Response.swift */; };
|
7A11474923FF2B2D00B424AF /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11474823FF2B2D00B424AF /* Response.swift */; };
|
||||||
@ -75,7 +74,6 @@
|
|||||||
7A7547E024032CB6004E8406 /* VehiclePhotoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A7547DF24032CB6004E8406 /* VehiclePhotoCell.swift */; };
|
7A7547E024032CB6004E8406 /* VehiclePhotoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A7547DF24032CB6004E8406 /* VehiclePhotoCell.swift */; };
|
||||||
7A8A2209248D10EC0073DFD9 /* ResizeImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A2208248D10EC0073DFD9 /* ResizeImage.swift */; };
|
7A8A2209248D10EC0073DFD9 /* ResizeImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A2208248D10EC0073DFD9 /* ResizeImage.swift */; };
|
||||||
7A8A220B248D67B60073DFD9 /* VehicleReportImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A220A248D67B60073DFD9 /* VehicleReportImage.swift */; };
|
7A8A220B248D67B60073DFD9 /* VehicleReportImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A220A248D67B60073DFD9 /* VehicleReportImage.swift */; };
|
||||||
7A8A220E248EF5830073DFD9 /* SwiftJWT in Frameworks */ = {isa = PBXBuildFile; productRef = 7A8A220D248EF5830073DFD9 /* SwiftJWT */; };
|
|
||||||
7A96AE2A246AFD6200297C33 /* Eureka in Frameworks */ = {isa = PBXBuildFile; productRef = 7A96AE29246AFD6200297C33 /* Eureka */; };
|
7A96AE2A246AFD6200297C33 /* Eureka in Frameworks */ = {isa = PBXBuildFile; productRef = 7A96AE29246AFD6200297C33 /* Eureka */; };
|
||||||
7A96AE2D246B2B7400297C33 /* GoogleSignInController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A96AE2C246B2B7400297C33 /* GoogleSignInController.swift */; };
|
7A96AE2D246B2B7400297C33 /* GoogleSignInController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A96AE2C246B2B7400297C33 /* GoogleSignInController.swift */; };
|
||||||
7A96AE2F246B2BCD00297C33 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A96AE2E246B2BCD00297C33 /* WebKit.framework */; };
|
7A96AE2F246B2BCD00297C33 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A96AE2E246B2BCD00297C33 /* WebKit.framework */; };
|
||||||
@ -177,11 +175,9 @@
|
|||||||
7A11472123FEA18700B424AF /* RxCocoa in Frameworks */,
|
7A11472123FEA18700B424AF /* RxCocoa in Frameworks */,
|
||||||
7A0516182414EC1200FC55AC /* RxDataSources in Frameworks */,
|
7A0516182414EC1200FC55AC /* RxDataSources in Frameworks */,
|
||||||
7A96AE2A246AFD6200297C33 /* Eureka in Frameworks */,
|
7A96AE2A246AFD6200297C33 /* Eureka in Frameworks */,
|
||||||
7A8A220E248EF5830073DFD9 /* SwiftJWT in Frameworks */,
|
|
||||||
7A051611241412CA00FC55AC /* SwiftDate in Frameworks */,
|
7A051611241412CA00FC55AC /* SwiftDate in Frameworks */,
|
||||||
7A11472323FEA18700B424AF /* RxBlocking in Frameworks */,
|
7A11472323FEA18700B424AF /* RxBlocking in Frameworks */,
|
||||||
7A530B8B240181F500CBFE6E /* RxRealm in Frameworks */,
|
7A530B8B240181F500CBFE6E /* RxRealm in Frameworks */,
|
||||||
7A11472B23FEA24D00B424AF /* Action in Frameworks */,
|
|
||||||
7A11471F23FEA18700B424AF /* RxRelay in Frameworks */,
|
7A11471F23FEA18700B424AF /* RxRelay in Frameworks */,
|
||||||
7AF58D2F24029C5200CE01A0 /* MagazineLayout in Frameworks */,
|
7AF58D2F24029C5200CE01A0 /* MagazineLayout in Frameworks */,
|
||||||
7A530B78240010D900CBFE6E /* InputMask in Frameworks */,
|
7A530B78240010D900CBFE6E /* InputMask in Frameworks */,
|
||||||
@ -405,7 +401,6 @@
|
|||||||
7A11472223FEA18700B424AF /* RxBlocking */,
|
7A11472223FEA18700B424AF /* RxBlocking */,
|
||||||
7A11472523FEA1F400B424AF /* Realm */,
|
7A11472523FEA1F400B424AF /* Realm */,
|
||||||
7A11472723FEA1F400B424AF /* RealmSwift */,
|
7A11472723FEA1F400B424AF /* RealmSwift */,
|
||||||
7A11472A23FEA24D00B424AF /* Action */,
|
|
||||||
7A530B77240010D900CBFE6E /* InputMask */,
|
7A530B77240010D900CBFE6E /* InputMask */,
|
||||||
7A530B8A240181F500CBFE6E /* RxRealm */,
|
7A530B8A240181F500CBFE6E /* RxRealm */,
|
||||||
7AF58D2E24029C5200CE01A0 /* MagazineLayout */,
|
7AF58D2E24029C5200CE01A0 /* MagazineLayout */,
|
||||||
@ -414,7 +409,6 @@
|
|||||||
7A0516152414EC1200FC55AC /* Differentiator */,
|
7A0516152414EC1200FC55AC /* Differentiator */,
|
||||||
7A0516172414EC1200FC55AC /* RxDataSources */,
|
7A0516172414EC1200FC55AC /* RxDataSources */,
|
||||||
7A96AE29246AFD6200297C33 /* Eureka */,
|
7A96AE29246AFD6200297C33 /* Eureka */,
|
||||||
7A8A220D248EF5830073DFD9 /* SwiftJWT */,
|
|
||||||
);
|
);
|
||||||
productName = AutoCat;
|
productName = AutoCat;
|
||||||
productReference = 7A1146FD23FDE7E500B424AF /* AutoCat.app */;
|
productReference = 7A1146FD23FDE7E500B424AF /* AutoCat.app */;
|
||||||
@ -447,7 +441,6 @@
|
|||||||
packageReferences = (
|
packageReferences = (
|
||||||
7A11471B23FEA18700B424AF /* XCRemoteSwiftPackageReference "RxSwift" */,
|
7A11471B23FEA18700B424AF /* XCRemoteSwiftPackageReference "RxSwift" */,
|
||||||
7A11472423FEA1F400B424AF /* XCRemoteSwiftPackageReference "realm-cocoa" */,
|
7A11472423FEA1F400B424AF /* XCRemoteSwiftPackageReference "realm-cocoa" */,
|
||||||
7A11472923FEA24D00B424AF /* XCRemoteSwiftPackageReference "Action" */,
|
|
||||||
7A530B76240010D900CBFE6E /* XCRemoteSwiftPackageReference "input-mask-ios" */,
|
7A530B76240010D900CBFE6E /* XCRemoteSwiftPackageReference "input-mask-ios" */,
|
||||||
7A530B89240181F500CBFE6E /* XCRemoteSwiftPackageReference "RxRealm" */,
|
7A530B89240181F500CBFE6E /* XCRemoteSwiftPackageReference "RxRealm" */,
|
||||||
7AF58D2D24029C5200CE01A0 /* XCRemoteSwiftPackageReference "MagazineLayout" */,
|
7AF58D2D24029C5200CE01A0 /* XCRemoteSwiftPackageReference "MagazineLayout" */,
|
||||||
@ -455,7 +448,6 @@
|
|||||||
7A05160F241412CA00FC55AC /* XCRemoteSwiftPackageReference "SwiftDate" */,
|
7A05160F241412CA00FC55AC /* XCRemoteSwiftPackageReference "SwiftDate" */,
|
||||||
7A0516142414EC1200FC55AC /* XCRemoteSwiftPackageReference "RxDataSources" */,
|
7A0516142414EC1200FC55AC /* XCRemoteSwiftPackageReference "RxDataSources" */,
|
||||||
7A96AE28246AFD6200297C33 /* XCRemoteSwiftPackageReference "Eureka" */,
|
7A96AE28246AFD6200297C33 /* XCRemoteSwiftPackageReference "Eureka" */,
|
||||||
7A8A220C248EF5830073DFD9 /* XCRemoteSwiftPackageReference "Swift-JWT" */,
|
|
||||||
);
|
);
|
||||||
productRefGroup = 7A1146FE23FDE7E500B424AF /* Products */;
|
productRefGroup = 7A1146FE23FDE7E500B424AF /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
@ -691,7 +683,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
|
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 16;
|
CURRENT_PROJECT_VERSION = 19;
|
||||||
DEVELOPMENT_TEAM = 46DTTB8X4S;
|
DEVELOPMENT_TEAM = 46DTTB8X4S;
|
||||||
INFOPLIST_FILE = AutoCat/Info.plist;
|
INFOPLIST_FILE = AutoCat/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
@ -713,7 +705,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
|
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 16;
|
CURRENT_PROJECT_VERSION = 19;
|
||||||
DEVELOPMENT_TEAM = 46DTTB8X4S;
|
DEVELOPMENT_TEAM = 46DTTB8X4S;
|
||||||
INFOPLIST_FILE = AutoCat/Info.plist;
|
INFOPLIST_FILE = AutoCat/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
@ -785,14 +777,6 @@
|
|||||||
minimumVersion = 5.0.0;
|
minimumVersion = 5.0.0;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
7A11472923FEA24D00B424AF /* XCRemoteSwiftPackageReference "Action" */ = {
|
|
||||||
isa = XCRemoteSwiftPackageReference;
|
|
||||||
repositoryURL = "https://github.com/RxSwiftCommunity/Action";
|
|
||||||
requirement = {
|
|
||||||
kind = upToNextMajorVersion;
|
|
||||||
minimumVersion = 4.0.1;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
7A530B76240010D900CBFE6E /* XCRemoteSwiftPackageReference "input-mask-ios" */ = {
|
7A530B76240010D900CBFE6E /* XCRemoteSwiftPackageReference "input-mask-ios" */ = {
|
||||||
isa = XCRemoteSwiftPackageReference;
|
isa = XCRemoteSwiftPackageReference;
|
||||||
repositoryURL = "https://github.com/RedMadRobot/input-mask-ios";
|
repositoryURL = "https://github.com/RedMadRobot/input-mask-ios";
|
||||||
@ -809,14 +793,6 @@
|
|||||||
minimumVersion = 3.0.0;
|
minimumVersion = 3.0.0;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
7A8A220C248EF5830073DFD9 /* XCRemoteSwiftPackageReference "Swift-JWT" */ = {
|
|
||||||
isa = XCRemoteSwiftPackageReference;
|
|
||||||
repositoryURL = "https://github.com/IBM-Swift/Swift-JWT.git";
|
|
||||||
requirement = {
|
|
||||||
kind = upToNextMajorVersion;
|
|
||||||
minimumVersion = 3.6.1;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
7A96AE28246AFD6200297C33 /* XCRemoteSwiftPackageReference "Eureka" */ = {
|
7A96AE28246AFD6200297C33 /* XCRemoteSwiftPackageReference "Eureka" */ = {
|
||||||
isa = XCRemoteSwiftPackageReference;
|
isa = XCRemoteSwiftPackageReference;
|
||||||
repositoryURL = "https://github.com/xmartlabs/Eureka";
|
repositoryURL = "https://github.com/xmartlabs/Eureka";
|
||||||
@ -889,11 +865,6 @@
|
|||||||
package = 7A11472423FEA1F400B424AF /* XCRemoteSwiftPackageReference "realm-cocoa" */;
|
package = 7A11472423FEA1F400B424AF /* XCRemoteSwiftPackageReference "realm-cocoa" */;
|
||||||
productName = RealmSwift;
|
productName = RealmSwift;
|
||||||
};
|
};
|
||||||
7A11472A23FEA24D00B424AF /* Action */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = 7A11472923FEA24D00B424AF /* XCRemoteSwiftPackageReference "Action" */;
|
|
||||||
productName = Action;
|
|
||||||
};
|
|
||||||
7A530B77240010D900CBFE6E /* InputMask */ = {
|
7A530B77240010D900CBFE6E /* InputMask */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = 7A530B76240010D900CBFE6E /* XCRemoteSwiftPackageReference "input-mask-ios" */;
|
package = 7A530B76240010D900CBFE6E /* XCRemoteSwiftPackageReference "input-mask-ios" */;
|
||||||
@ -904,11 +875,6 @@
|
|||||||
package = 7A530B89240181F500CBFE6E /* XCRemoteSwiftPackageReference "RxRealm" */;
|
package = 7A530B89240181F500CBFE6E /* XCRemoteSwiftPackageReference "RxRealm" */;
|
||||||
productName = RxRealm;
|
productName = RxRealm;
|
||||||
};
|
};
|
||||||
7A8A220D248EF5830073DFD9 /* SwiftJWT */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = 7A8A220C248EF5830073DFD9 /* XCRemoteSwiftPackageReference "Swift-JWT" */;
|
|
||||||
productName = SwiftJWT;
|
|
||||||
};
|
|
||||||
7A96AE29246AFD6200297C33 /* Eureka */ = {
|
7A96AE29246AFD6200297C33 /* Eureka */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = 7A96AE28246AFD6200297C33 /* XCRemoteSwiftPackageReference "Eureka" */;
|
package = 7A96AE28246AFD6200297C33 /* XCRemoteSwiftPackageReference "Eureka" */;
|
||||||
|
|||||||
@ -1,42 +1,6 @@
|
|||||||
{
|
{
|
||||||
"object": {
|
"object": {
|
||||||
"pins": [
|
"pins": [
|
||||||
{
|
|
||||||
"package": "Action",
|
|
||||||
"repositoryURL": "https://github.com/RxSwiftCommunity/Action",
|
|
||||||
"state": {
|
|
||||||
"branch": null,
|
|
||||||
"revision": "1079e557787a3ffe88f833eb5f637dcf1396421b",
|
|
||||||
"version": "4.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"package": "Cryptor",
|
|
||||||
"repositoryURL": "https://github.com/IBM-Swift/BlueCryptor.git",
|
|
||||||
"state": {
|
|
||||||
"branch": null,
|
|
||||||
"revision": "12d2bf3ec7207ec3cd004b9582f69ef5fae1da3b",
|
|
||||||
"version": "1.0.32"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"package": "CryptorECC",
|
|
||||||
"repositoryURL": "https://github.com/IBM-Swift/BlueECC.git",
|
|
||||||
"state": {
|
|
||||||
"branch": null,
|
|
||||||
"revision": "73f362cb0d9c5f1fd0089240d7b293cd2bff18db",
|
|
||||||
"version": "1.2.5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"package": "CryptorRSA",
|
|
||||||
"repositoryURL": "https://github.com/IBM-Swift/BlueRSA.git",
|
|
||||||
"state": {
|
|
||||||
"branch": null,
|
|
||||||
"revision": "8ea901f2582296837d88f882b0fa5a0601759598",
|
|
||||||
"version": "1.0.35"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"package": "Eureka",
|
"package": "Eureka",
|
||||||
"repositoryURL": "https://github.com/xmartlabs/Eureka",
|
"repositoryURL": "https://github.com/xmartlabs/Eureka",
|
||||||
@ -64,24 +28,6 @@
|
|||||||
"version": "5.14.0"
|
"version": "5.14.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"package": "KituraContracts",
|
|
||||||
"repositoryURL": "https://github.com/IBM-Swift/KituraContracts.git",
|
|
||||||
"state": {
|
|
||||||
"branch": null,
|
|
||||||
"revision": "a30e2fb79e926672776a05ec6b919c239870a221",
|
|
||||||
"version": "1.2.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"package": "LoggerAPI",
|
|
||||||
"repositoryURL": "https://github.com/IBM-Swift/LoggerAPI.git",
|
|
||||||
"state": {
|
|
||||||
"branch": null,
|
|
||||||
"revision": "3357dd9526cdf9436fa63bb792b669e6efdc43da",
|
|
||||||
"version": "1.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"package": "MagazineLayout",
|
"package": "MagazineLayout",
|
||||||
"repositoryURL": "https://github.com/airbnb/MagazineLayout",
|
"repositoryURL": "https://github.com/airbnb/MagazineLayout",
|
||||||
@ -136,24 +82,6 @@
|
|||||||
"version": "5.1.1"
|
"version": "5.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"package": "SwiftJWT",
|
|
||||||
"repositoryURL": "https://github.com/IBM-Swift/Swift-JWT.git",
|
|
||||||
"state": {
|
|
||||||
"branch": null,
|
|
||||||
"revision": "0d435423d12e61c0d14adb6d04396c08a6a650f1",
|
|
||||||
"version": "3.6.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"package": "swift-log",
|
|
||||||
"repositoryURL": "https://github.com/apple/swift-log.git",
|
|
||||||
"state": {
|
|
||||||
"branch": null,
|
|
||||||
"revision": "74d7b91ceebc85daf387ebb206003f78813f71aa",
|
|
||||||
"version": "1.2.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"package": "SwiftDate",
|
"package": "SwiftDate",
|
||||||
"repositoryURL": "https://github.com/malcommac/SwiftDate.git",
|
"repositoryURL": "https://github.com/malcommac/SwiftDate.git",
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
BreakpointExtensionID = "Xcode.Breakpoint.SwiftErrorBreakpoint">
|
BreakpointExtensionID = "Xcode.Breakpoint.SwiftErrorBreakpoint">
|
||||||
<BreakpointContent
|
<BreakpointContent
|
||||||
uuid = "C14D0996-5708-44D2-A6BA-4A4B50B522EE"
|
uuid = "C14D0996-5708-44D2-A6BA-4A4B50B522EE"
|
||||||
shouldBeEnabled = "No"
|
shouldBeEnabled = "Yes"
|
||||||
ignoreCount = "0"
|
ignoreCount = "0"
|
||||||
continueAfterRunningActions = "No">
|
continueAfterRunningActions = "No">
|
||||||
</BreakpointContent>
|
</BreakpointContent>
|
||||||
@ -17,29 +17,13 @@
|
|||||||
BreakpointExtensionID = "Xcode.Breakpoint.ExceptionBreakpoint">
|
BreakpointExtensionID = "Xcode.Breakpoint.ExceptionBreakpoint">
|
||||||
<BreakpointContent
|
<BreakpointContent
|
||||||
uuid = "CF01B44D-372B-4C78-A197-7FDEC607CE0E"
|
uuid = "CF01B44D-372B-4C78-A197-7FDEC607CE0E"
|
||||||
shouldBeEnabled = "No"
|
shouldBeEnabled = "Yes"
|
||||||
ignoreCount = "0"
|
ignoreCount = "0"
|
||||||
continueAfterRunningActions = "No"
|
continueAfterRunningActions = "No"
|
||||||
scope = "1"
|
scope = "1"
|
||||||
stopOnStyle = "0">
|
stopOnStyle = "0">
|
||||||
</BreakpointContent>
|
</BreakpointContent>
|
||||||
</BreakpointProxy>
|
</BreakpointProxy>
|
||||||
<BreakpointProxy
|
|
||||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
|
||||||
<BreakpointContent
|
|
||||||
uuid = "143FAB5A-C171-426A-A0BA-67C44E72B9D5"
|
|
||||||
shouldBeEnabled = "No"
|
|
||||||
ignoreCount = "0"
|
|
||||||
continueAfterRunningActions = "No"
|
|
||||||
filePath = "AutoCat/Controllers/GoogleSignInController.swift"
|
|
||||||
startingColumnNumber = "9223372036854775807"
|
|
||||||
endingColumnNumber = "9223372036854775807"
|
|
||||||
startingLineNumber = "61"
|
|
||||||
endingLineNumber = "61"
|
|
||||||
landmarkName = "webView(_:decidePolicyFor:decisionHandler:)"
|
|
||||||
landmarkType = "7">
|
|
||||||
</BreakpointContent>
|
|
||||||
</BreakpointProxy>
|
|
||||||
<BreakpointProxy
|
<BreakpointProxy
|
||||||
BreakpointExtensionID = "Xcode.Breakpoint.SymbolicBreakpoint">
|
BreakpointExtensionID = "Xcode.Breakpoint.SymbolicBreakpoint">
|
||||||
<BreakpointContent
|
<BreakpointContent
|
||||||
|
|||||||
@ -405,14 +405,14 @@
|
|||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="44.5"/>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||||
</view>
|
</view>
|
||||||
<stackView opaque="NO" contentMode="scaleToFill" spacing="12" translatesAutoresizingMaskIntoConstraints="NO" id="QSJ-FJ-C4c">
|
<stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="12" translatesAutoresizingMaskIntoConstraints="NO" id="QSJ-FJ-C4c">
|
||||||
<rect key="frame" x="8" y="0.0" width="359" height="44.5"/>
|
<rect key="frame" x="8" y="0.0" width="359" height="44.5"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="BKm-HE-Aor">
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="BKm-HE-Aor">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="44.5" height="44.5"/>
|
<rect key="frame" x="0.0" y="0.5" width="44" height="44"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" constant="44" id="I8M-qD-lKL"/>
|
|
||||||
<constraint firstAttribute="width" secondItem="BKm-HE-Aor" secondAttribute="height" multiplier="1:1" id="Y4G-Ki-oYP"/>
|
<constraint firstAttribute="width" secondItem="BKm-HE-Aor" secondAttribute="height" multiplier="1:1" id="Y4G-Ki-oYP"/>
|
||||||
|
<constraint firstAttribute="height" constant="44" id="lQk-Ob-dxJ"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<state key="normal" image="play.fill" catalog="system"/>
|
<state key="normal" image="play.fill" catalog="system"/>
|
||||||
<connections>
|
<connections>
|
||||||
@ -420,19 +420,19 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" text="00:00" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bFQ-eU-5YJ">
|
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" text="00:00" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bFQ-eU-5YJ">
|
||||||
<rect key="frame" x="50.5" y="0.0" width="0.0" height="44.5"/>
|
<rect key="frame" x="50" y="12" width="0.0" height="20.5"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<color key="textColor" systemColor="systemTealColor" red="0.35294117650000001" green="0.7843137255" blue="0.98039215690000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" systemColor="systemTealColor" red="0.35294117650000001" green="0.7843137255" blue="0.98039215690000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MjS-Hy-iGH">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MjS-Hy-iGH">
|
||||||
<rect key="frame" x="56.5" y="0.0" width="253" height="44.5"/>
|
<rect key="frame" x="56" y="10.5" width="253.5" height="24"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="20"/>
|
<fontDescription key="fontDescription" type="system" pointSize="20"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Jgb-TO-YHq">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Jgb-TO-YHq">
|
||||||
<rect key="frame" x="321.5" y="0.0" width="37.5" height="44.5"/>
|
<rect key="frame" x="321.5" y="13.5" width="37.5" height="18"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||||
<color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
@ -830,11 +830,11 @@
|
|||||||
<image name="doc.on.doc" catalog="system" width="117" height="128"/>
|
<image name="doc.on.doc" catalog="system" width="117" height="128"/>
|
||||||
<image name="line.horizontal.3.decrease" catalog="system" width="128" height="73"/>
|
<image name="line.horizontal.3.decrease" catalog="system" width="128" height="73"/>
|
||||||
<image name="play.fill" catalog="system" width="116" height="128"/>
|
<image name="play.fill" catalog="system" width="116" height="128"/>
|
||||||
<image name="record" width="31" height="31"/>
|
<image name="record" width="128" height="128"/>
|
||||||
<image name="record-compact" width="23" height="23"/>
|
<image name="record-compact" width="23" height="23"/>
|
||||||
<image name="search" width="23" height="23"/>
|
<image name="search" width="128" height="128"/>
|
||||||
<image name="search-compact" width="17" height="17"/>
|
<image name="search-compact" width="17" height="17"/>
|
||||||
<image name="settings" width="25" height="25"/>
|
<image name="settings" width="128" height="128"/>
|
||||||
<image name="settings-compact" width="18" height="18"/>
|
<image name="settings-compact" width="18" height="18"/>
|
||||||
</resources>
|
</resources>
|
||||||
</document>
|
</document>
|
||||||
|
|||||||
@ -74,6 +74,7 @@ class AudioRecordCell: UITableViewCell {
|
|||||||
try AudioPlayer.shared.play(url: url)
|
try AudioPlayer.shared.play(url: url)
|
||||||
} catch {
|
} catch {
|
||||||
print("Error playing audio record: \(error.localizedDescription)")
|
print("Error playing audio record: \(error.localizedDescription)")
|
||||||
|
IHProgressHUD.showError(withStatus: error.localizedDescription)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -120,6 +120,7 @@ class RecordsController: UIViewController, UITableViewDelegate {
|
|||||||
let date = Date()
|
let date = Date()
|
||||||
let fileName = "recording-\(date.timeIntervalSince1970).m4a"
|
let fileName = "recording-\(date.timeIntervalSince1970).m4a"
|
||||||
let url = try FileManager.default.url(for: fileName, in: "recordings")
|
let url = try FileManager.default.url(for: fileName, in: "recordings")
|
||||||
|
try self.makeStartSoundIfNeeded {
|
||||||
try recorder.startRecording(to: url) { result in
|
try recorder.startRecording(to: url) { result in
|
||||||
let asset = AVURLAsset(url: url)
|
let asset = AVURLAsset(url: url)
|
||||||
let duration = TimeInterval(CMTimeGetSeconds(asset.duration))
|
let duration = TimeInterval(CMTimeGetSeconds(asset.duration))
|
||||||
@ -129,6 +130,8 @@ class RecordsController: UIViewController, UITableViewDelegate {
|
|||||||
realm?.add(record)
|
realm?.add(record)
|
||||||
}
|
}
|
||||||
alert.dismiss(animated: true)
|
alert.dismiss(animated: true)
|
||||||
|
print("New record saved to: \(url.path)")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.donateUserActivity()
|
self.donateUserActivity()
|
||||||
} catch {
|
} catch {
|
||||||
@ -150,14 +153,14 @@ class RecordsController: UIViewController, UITableViewDelegate {
|
|||||||
var result = ""
|
var result = ""
|
||||||
if let range = trimmed.range(of: #"\S\d\d\d\S\S\d\d\d?"#, options: .regularExpression) {
|
if let range = trimmed.range(of: #"\S\d\d\d\S\S\d\d\d?"#, options: .regularExpression) {
|
||||||
result = String(trimmed[range])
|
result = String(trimmed[range])
|
||||||
} else if let range = trimmed.range(of: #"\S\S\S\d\d\d\d\d\d?"#, options: .regularExpression) {
|
} else if let range = trimmed.range(of: #"\S\S\S\d\d\d\d\d\d?"#, options: .regularExpression), Settings.shared.recognizeAlternativeOrder {
|
||||||
let n = String(trimmed[range])
|
let n = String(trimmed[range])
|
||||||
result = String(n.prefix(1)) + n.substring(with: 3..<6) + n.substring(with: 1..<3) + n.substring(from: 6)
|
result = String(n.prefix(1)) + n.substring(with: 3..<6) + n.substring(with: 1..<3) + n.substring(from: 6)
|
||||||
} else if let range = trimmed.range(of: #"\S\d\d\d\S\S\d\d\d?"#, options: .regularExpression) {
|
} else if let range = trimmed.range(of: #"\S\d\d\d\S\S"#, options: .regularExpression), Settings.shared.recognizeShortenedNumbers {
|
||||||
result = String(trimmed[range]) + "161"
|
result = String(trimmed[range]) + Settings.shared.defaultRegion
|
||||||
} else if let range = trimmed.range(of: #"\S\S\S\d\d\d"#, options: .regularExpression) {
|
} else if let range = trimmed.range(of: #"\S\S\S\d\d\d"#, options: .regularExpression), Settings.shared.recognizeAlternativeOrder && Settings.shared.recognizeShortenedNumbers {
|
||||||
let n = String(trimmed[range])
|
let n = String(trimmed[range])
|
||||||
result = n.prefix(1) + n.substring(with: 3..<6) + n.substring(with: 1..<3) + "161"
|
result = String(n.prefix(1)) + n.substring(with: 3..<6) + n.substring(with: 1..<3) + Settings.shared.defaultRegion
|
||||||
}
|
}
|
||||||
|
|
||||||
if !result.isEmpty && valid(number: result) {
|
if !result.isEmpty && valid(number: result) {
|
||||||
@ -177,6 +180,32 @@ class RecordsController: UIViewController, UITableViewDelegate {
|
|||||||
&& self.validLetters.contains(third)
|
&& self.validLetters.contains(third)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeStartSoundIfNeeded(completion: @escaping () throws -> Void) throws {
|
||||||
|
if !Settings.shared.recordBeep {
|
||||||
|
try completion()
|
||||||
|
} else {
|
||||||
|
//let session = AVAudioSession.sharedInstance()
|
||||||
|
//try session.setCategory(.playback, mode: .default, options: [.defaultToSpeaker])
|
||||||
|
//try session.setActive(true)
|
||||||
|
var err: Error?
|
||||||
|
var soundId = SystemSoundID()
|
||||||
|
let url = URL(fileURLWithPath: "/System/Library/Audio/UISounds/short_double_high.caf")
|
||||||
|
AudioServicesCreateSystemSoundID(url as CFURL, &soundId)
|
||||||
|
AudioServicesPlaySystemSoundWithCompletion(soundId) {
|
||||||
|
do {
|
||||||
|
//try session.setActive(false)
|
||||||
|
try completion()
|
||||||
|
} catch {
|
||||||
|
err = error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let error = err {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - UITableViewDelegate
|
// MARK: - UITableViewDelegate
|
||||||
|
|
||||||
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
|
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import UIKit
|
|||||||
import MagazineLayout
|
import MagazineLayout
|
||||||
import Kingfisher
|
import Kingfisher
|
||||||
import LinkPresentation
|
import LinkPresentation
|
||||||
import SwiftJWT
|
|
||||||
|
|
||||||
enum ReportSection: Int, CaseIterable, CustomStringConvertible {
|
enum ReportSection: Int, CaseIterable, CustomStringConvertible {
|
||||||
case header = 0
|
case header = 0
|
||||||
@ -76,12 +75,6 @@ enum ReportEngineSection: Int, CaseIterable, CustomStringConvertible {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ReportLinkClaims: Claims {
|
|
||||||
let exp: Date
|
|
||||||
let iat: Date
|
|
||||||
let plateNumber: String
|
|
||||||
}
|
|
||||||
|
|
||||||
class ReportController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateMagazineLayout, MediaBrowserViewControllerDataSource, MediaBrowserViewControllerDelegate, UIActivityItemSource {
|
class ReportController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateMagazineLayout, MediaBrowserViewControllerDataSource, MediaBrowserViewControllerDelegate, UIActivityItemSource {
|
||||||
|
|
||||||
@IBOutlet weak var collection: UICollectionView!
|
@IBOutlet weak var collection: UICollectionView!
|
||||||
@ -397,12 +390,7 @@ class ReportController: UIViewController, UICollectionViewDataSource, UICollecti
|
|||||||
let shareLink = UIAlertAction(title: "As link", style: .default) { _ in
|
let shareLink = UIAlertAction(title: "As link", style: .default) { _ in
|
||||||
guard let vehicle = self.vehicle else { return }
|
guard let vehicle = self.vehicle else { return }
|
||||||
|
|
||||||
let iat = Date()
|
if let jwt = try? JWT.generate(for: vehicle.number), let url = URL(string: Constants.reportLinkBaseURL + "?token=" + jwt) {
|
||||||
let exp = Date(timeIntervalSinceNow: 24*60*60)
|
|
||||||
let claims = ReportLinkClaims(exp: exp, iat: iat, plateNumber: vehicle.number)
|
|
||||||
let signer = JWTSigner.hs256(key: Constants.reportLinkTokenSecret.data(using: .utf8)!)
|
|
||||||
var jwt = SwiftJWT.JWT(claims: claims)
|
|
||||||
if let jwtSigned = try? jwt.sign(using: signer), let url = URL(string: Constants.reportLinkBaseURL + "?token=" + jwtSigned) {
|
|
||||||
let controller = UIActivityViewController(activityItems: [url], applicationActivities: nil)
|
let controller = UIActivityViewController(activityItems: [url], applicationActivities: nil)
|
||||||
controller.popoverPresentationController?.barButtonItem = sender
|
controller.popoverPresentationController?.barButtonItem = sender
|
||||||
self.present(controller, animated: true)
|
self.present(controller, animated: true)
|
||||||
|
|||||||
@ -28,7 +28,50 @@ class SettingsController: FormViewController {
|
|||||||
self.loginToGoogle()
|
self.loginToGoogle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+++ Section()
|
|
||||||
|
+++ Section(header: "Plate number recognition", footer: "Recognize plate numbers in alternative form. For example 'ЕВА 123 777' instead of 'Е123ВА 777'")
|
||||||
|
<<< SwitchRow("AlternateRecognition") { row in
|
||||||
|
row.title = "Alternative order"
|
||||||
|
row.value = Settings.shared.recognizeAlternativeOrder
|
||||||
|
}.onChange { row in
|
||||||
|
if let val = row.value {
|
||||||
|
Settings.shared.recognizeAlternativeOrder = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+++ Section(footer: "If enabled, app will try to recognize shortened plate numbers (without region) and add default region")
|
||||||
|
<<< SwitchRow("ShortenedNumbers") { row in
|
||||||
|
row.title = "Shortened numbers"
|
||||||
|
row.value = Settings.shared.recognizeShortenedNumbers
|
||||||
|
}.onChange { row in
|
||||||
|
if let val = row.value {
|
||||||
|
Settings.shared.recognizeShortenedNumbers = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
<<< TextRow("") { row in
|
||||||
|
row.title = "Default region"
|
||||||
|
row.placeholder = "161"
|
||||||
|
row.value = Settings.shared.defaultRegion
|
||||||
|
row.hidden = Condition.function(["ShortenedNumbers"], { form in
|
||||||
|
return !((form.rowBy(tag: "ShortenedNumbers") as? SwitchRow)?.value ?? false)
|
||||||
|
})
|
||||||
|
}.onChange { row in
|
||||||
|
if let val = row.value {
|
||||||
|
Settings.shared.defaultRegion = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+++ Section(footer: "When enabled, you will hear short sound before starting audio recording. This will only work when audio record is started via Siri")
|
||||||
|
<<< SwitchRow("BeepRecord") { row in
|
||||||
|
row.title = "Beep before record"
|
||||||
|
row.value = Settings.shared.recordBeep
|
||||||
|
}.onChange{ row in
|
||||||
|
if let val = row.value {
|
||||||
|
Settings.shared.recordBeep = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+++ Section("")
|
||||||
<<< ButtonRow("SignOut") { $0.title = "Sign Out" }.onCellSelection { cell, row in
|
<<< ButtonRow("SignOut") { $0.title = "Sign Out" }.onCellSelection { cell, row in
|
||||||
self.logout()
|
self.logout()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,10 +2,6 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSSpeechRecognitionUsageDescription</key>
|
|
||||||
<string>Access is needed for recognizing plate numbers from voice recordings</string>
|
|
||||||
<key>NSMicrophoneUsageDescription</key>
|
|
||||||
<string>Access is needed for voice recordings</string>
|
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
@ -46,8 +42,12 @@
|
|||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
|
<key>NSMicrophoneUsageDescription</key>
|
||||||
|
<string>Access is needed for voice recordings</string>
|
||||||
<key>NSPhotoLibraryAddUsageDescription</key>
|
<key>NSPhotoLibraryAddUsageDescription</key>
|
||||||
<string>AutoCat needs access to photo library to save reports</string>
|
<string>AutoCat needs access to photo library to save reports</string>
|
||||||
|
<key>NSSpeechRecognitionUsageDescription</key>
|
||||||
|
<string>Access is needed for recognizing plate numbers from voice recordings</string>
|
||||||
<key>UIAppFonts</key>
|
<key>UIAppFonts</key>
|
||||||
<array>
|
<array>
|
||||||
<string>RoadNumbers2.0.otf</string>
|
<string>RoadNumbers2.0.otf</string>
|
||||||
@ -74,12 +74,12 @@
|
|||||||
<key>UIApplicationShortcutItems</key>
|
<key>UIApplicationShortcutItems</key>
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
<key>UIApplicationShortcutItemType</key>
|
|
||||||
<string>AddVoiceRecordAction</string>
|
|
||||||
<key>UIApplicationShortcutItemTitle</key>
|
|
||||||
<string>Add voice record</string>
|
|
||||||
<key>UIApplicationShortcutItemIconType</key>
|
<key>UIApplicationShortcutItemIconType</key>
|
||||||
<string>UIApplicationShortcutIconTypeAudio</string>
|
<string>UIApplicationShortcutIconTypeAudio</string>
|
||||||
|
<key>UIApplicationShortcutItemTitle</key>
|
||||||
|
<string>Add voice record</string>
|
||||||
|
<key>UIApplicationShortcutItemType</key>
|
||||||
|
<string>AddVoiceRecordAction</string>
|
||||||
</dict>
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
<key>UIApplicationShortcutItemIconType</key>
|
<key>UIApplicationShortcutItemIconType</key>
|
||||||
|
|||||||
@ -13,8 +13,47 @@ class Settings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var recognizeAlternativeOrder: Bool = false {
|
||||||
|
didSet {
|
||||||
|
Settings.defaults.set(self.recognizeAlternativeOrder, forKey: "recognizeAlternativeOrder")
|
||||||
|
Settings.defaults.synchronize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var recognizeShortenedNumbers: Bool = false {
|
||||||
|
didSet {
|
||||||
|
Settings.defaults.set(self.recognizeShortenedNumbers, forKey: "recognizeShortenedNumbers")
|
||||||
|
Settings.defaults.synchronize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var defaultRegion: String = "" {
|
||||||
|
didSet {
|
||||||
|
Settings.defaults.set(self.defaultRegion, forKey: "defaultRegion")
|
||||||
|
Settings.defaults.synchronize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var recordBeep: Bool = false {
|
||||||
|
didSet {
|
||||||
|
Settings.defaults.set(self.recordBeep, forKey: "recordBeep")
|
||||||
|
Settings.defaults.synchronize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
|
UserDefaults.standard.register(defaults: [
|
||||||
|
"recognizeAlternativeOrder": false,
|
||||||
|
"recognizeShortenedNumbers": false,
|
||||||
|
"defaultRegion": "161",
|
||||||
|
"recordBeep": false
|
||||||
|
])
|
||||||
|
|
||||||
self.user = Settings.getUser()
|
self.user = Settings.getUser()
|
||||||
|
self.recognizeAlternativeOrder = Settings.defaults.bool(forKey: "recognizeAlternativeOrder")
|
||||||
|
self.recognizeShortenedNumbers = Settings.defaults.bool(forKey: "recognizeShortenedNumbers")
|
||||||
|
self.defaultRegion = Settings.defaults.string(forKey: "defaultRegion") ?? "161"
|
||||||
|
self.recordBeep = Settings.defaults.bool(forKey: "recordBeep")
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func getUser() -> User {
|
private static func getUser() -> User {
|
||||||
|
|||||||
4
AutoCat/ThirdParty/Base64FS.swift
vendored
4
AutoCat/ThirdParty/Base64FS.swift
vendored
@ -149,11 +149,11 @@ public class Base64FS {
|
|||||||
public static func encodeString(str: String) -> String {
|
public static func encodeString(str: String) -> String {
|
||||||
|
|
||||||
// Get the ascii representation and return
|
// Get the ascii representation and return
|
||||||
let data = str.data(using: .ascii)!
|
let data = str.data(using: .utf8)!
|
||||||
|
|
||||||
let encData = encode(data: [UInt8](data))
|
let encData = encode(data: [UInt8](data))
|
||||||
|
|
||||||
let retStr = String(data: Data(encData), encoding: .ascii)!
|
let retStr = String(data: Data(encData), encoding: .utf8)!
|
||||||
|
|
||||||
return retStr
|
return retStr
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,12 +30,15 @@ class AudioPlayer: NSObject, AVAudioPlayerDelegate {
|
|||||||
self.player?.delegate = self
|
self.player?.delegate = self
|
||||||
}
|
}
|
||||||
|
|
||||||
func play() {
|
func play() throws {
|
||||||
if let player = self.player {
|
if let player = self.player {
|
||||||
if player.isPlaying {
|
if player.isPlaying {
|
||||||
player.pause()
|
player.pause()
|
||||||
|
try AVAudioSession.sharedInstance().setActive(false)
|
||||||
self.state.accept(.paused)
|
self.state.accept(.paused)
|
||||||
} else {
|
} else {
|
||||||
|
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [.defaultToSpeaker])
|
||||||
|
try AVAudioSession.sharedInstance().setActive(true)
|
||||||
player.play()
|
player.play()
|
||||||
self.state.accept(.playing)
|
self.state.accept(.playing)
|
||||||
if self.progressTimer == nil {
|
if self.progressTimer == nil {
|
||||||
@ -47,12 +50,13 @@ class AudioPlayer: NSObject, AVAudioPlayerDelegate {
|
|||||||
|
|
||||||
func play(url: URL) throws {
|
func play(url: URL) throws {
|
||||||
try self.set(url: url)
|
try self.set(url: url)
|
||||||
self.play()
|
try self.play()
|
||||||
}
|
}
|
||||||
|
|
||||||
func pause() {
|
func pause() {
|
||||||
if let player = self.player {
|
if let player = self.player {
|
||||||
player.pause()
|
player.pause()
|
||||||
|
try? AVAudioSession.sharedInstance().setActive(false)
|
||||||
self.state.accept(.paused)
|
self.state.accept(.paused)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,6 +64,7 @@ class AudioPlayer: NSObject, AVAudioPlayerDelegate {
|
|||||||
func stop() {
|
func stop() {
|
||||||
if let player = self.player {
|
if let player = self.player {
|
||||||
player.stop()
|
player.stop()
|
||||||
|
try? AVAudioSession.sharedInstance().setActive(false)
|
||||||
self.state.accept(.stopped)
|
self.state.accept(.stopped)
|
||||||
self.progressTimer?.invalidate()
|
self.progressTimer?.invalidate()
|
||||||
self.progressTimer = nil
|
self.progressTimer = nil
|
||||||
@ -93,6 +98,7 @@ class AudioPlayer: NSObject, AVAudioPlayerDelegate {
|
|||||||
// MARK: - AVAudioPlayerDelegate
|
// MARK: - AVAudioPlayerDelegate
|
||||||
|
|
||||||
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
|
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
|
||||||
|
try? AVAudioSession.sharedInstance().setActive(false)
|
||||||
self.progress.accept(1)
|
self.progress.accept(1)
|
||||||
self.stop()
|
self.stop()
|
||||||
self.state.accept(.stopped)
|
self.state.accept(.stopped)
|
||||||
|
|||||||
@ -1,4 +1,65 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
import CommonCrypto
|
||||||
|
|
||||||
|
enum CryptoAlgorithm {
|
||||||
|
case MD5, SHA1, SHA224, SHA256, SHA384, SHA512
|
||||||
|
|
||||||
|
var HMACAlgorithm: CCHmacAlgorithm {
|
||||||
|
var result: Int = 0
|
||||||
|
switch self {
|
||||||
|
case .MD5: result = kCCHmacAlgMD5
|
||||||
|
case .SHA1: result = kCCHmacAlgSHA1
|
||||||
|
case .SHA224: result = kCCHmacAlgSHA224
|
||||||
|
case .SHA256: result = kCCHmacAlgSHA256
|
||||||
|
case .SHA384: result = kCCHmacAlgSHA384
|
||||||
|
case .SHA512: result = kCCHmacAlgSHA512
|
||||||
|
}
|
||||||
|
return CCHmacAlgorithm(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
var digestLength: Int {
|
||||||
|
var result: Int32 = 0
|
||||||
|
switch self {
|
||||||
|
case .MD5: result = CC_MD5_DIGEST_LENGTH
|
||||||
|
case .SHA1: result = CC_SHA1_DIGEST_LENGTH
|
||||||
|
case .SHA224: result = CC_SHA224_DIGEST_LENGTH
|
||||||
|
case .SHA256: result = CC_SHA256_DIGEST_LENGTH
|
||||||
|
case .SHA384: result = CC_SHA384_DIGEST_LENGTH
|
||||||
|
case .SHA512: result = CC_SHA512_DIGEST_LENGTH
|
||||||
|
}
|
||||||
|
return Int(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension String {
|
||||||
|
|
||||||
|
func hmac(algorithm: CryptoAlgorithm, key: String) -> String {
|
||||||
|
let str = self.cString(using: String.Encoding.utf8)
|
||||||
|
let strLen = Int(self.lengthOfBytes(using: String.Encoding.utf8))
|
||||||
|
let digestLen = algorithm.digestLength
|
||||||
|
let result = UnsafeMutablePointer<UInt8>.allocate(capacity: digestLen)
|
||||||
|
let keyStr = key.cString(using: String.Encoding.utf8)
|
||||||
|
let keyLen = Int(key.lengthOfBytes(using: String.Encoding.utf8))
|
||||||
|
|
||||||
|
CCHmac(algorithm.HMACAlgorithm, keyStr!, keyLen, str!, strLen, result)
|
||||||
|
|
||||||
|
let array = Array(UnsafeBufferPointer(start: result, count: digestLen))
|
||||||
|
let encodedArray = Base64FS.encode(data: array)
|
||||||
|
let string = String(data: Data(encodedArray), encoding: .utf8)!.trimmingCharacters(in: CharacterSet(charactersIn: "="))
|
||||||
|
|
||||||
|
result.deallocate()
|
||||||
|
|
||||||
|
return string
|
||||||
|
}
|
||||||
|
|
||||||
|
private func stringFromResult(result: UnsafeMutablePointer<CUnsignedChar>, length: Int) -> String {
|
||||||
|
let hash = NSMutableString()
|
||||||
|
for i in 0..<length {
|
||||||
|
hash.appendFormat("%02x", result[i])
|
||||||
|
}
|
||||||
|
return String(hash).lowercased()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct JwtPayload: Codable {
|
struct JwtPayload: Codable {
|
||||||
var email: String
|
var email: String
|
||||||
@ -35,4 +96,21 @@ class JWT {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func generate(for plateNumber: String) throws -> String {
|
||||||
|
let header = #"{ "typ": "JWT", "alg": "HS256" }"#
|
||||||
|
let bodyDict: [String: Any] = [
|
||||||
|
"iat": Date().timeIntervalSince1970,
|
||||||
|
"exp": Date(timeIntervalSinceNow: 24*60*60).timeIntervalSince1970,
|
||||||
|
"plateNumber": plateNumber
|
||||||
|
]
|
||||||
|
let bodyData = try JSONSerialization.data(withJSONObject: bodyDict, options: [])
|
||||||
|
|
||||||
|
guard let body = String(data: bodyData, encoding: .utf8) else {
|
||||||
|
throw CocoaError.error("Error", suggestion: "Error generating JWT for sharing report via link")
|
||||||
|
}
|
||||||
|
let twoParts = Base64FS.encodeString(str: header).trimmingCharacters(in: CharacterSet(charactersIn: "=")) + "." + Base64FS.encodeString(str: body).trimmingCharacters(in: CharacterSet(charactersIn: "="))
|
||||||
|
let signature = twoParts.hmac(algorithm: .SHA256, key: Constants.reportLinkTokenSecret)
|
||||||
|
return twoParts + "." + signature
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import AudioToolbox
|
|||||||
|
|
||||||
class Recorder {
|
class Recorder {
|
||||||
|
|
||||||
let session = AVAudioSession.sharedInstance()
|
|
||||||
let engine = AVAudioEngine()
|
let engine = AVAudioEngine()
|
||||||
var fileRef: ExtAudioFileRef? = nil
|
var fileRef: ExtAudioFileRef? = nil
|
||||||
let recognizer = SFSpeechRecognizer(locale: Locale(identifier: "ru_RU"))
|
let recognizer = SFSpeechRecognizer(locale: Locale(identifier: "ru_RU"))
|
||||||
@ -23,13 +22,11 @@ class Recorder {
|
|||||||
AVEncoderAudioQualityKey:AVAudioQuality.max.rawValue
|
AVEncoderAudioQualityKey:AVAudioQuality.max.rawValue
|
||||||
]
|
]
|
||||||
|
|
||||||
init() throws {
|
init() {
|
||||||
|
|
||||||
try self.session.setCategory(.record, mode: .spokenAudio, options: .mixWithOthers)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func requestPermissions(completion: @escaping (NSError?) -> Void) {
|
func requestPermissions(completion: @escaping (NSError?) -> Void) {
|
||||||
self.session.requestRecordPermission { allowed in
|
AVAudioSession.sharedInstance().requestRecordPermission { allowed in
|
||||||
if allowed {
|
if allowed {
|
||||||
SFSpeechRecognizer.requestAuthorization { status in
|
SFSpeechRecognizer.requestAuthorization { status in
|
||||||
switch status {
|
switch status {
|
||||||
@ -72,8 +69,8 @@ class Recorder {
|
|||||||
throw CocoaError.error(CocoaError.Code.fileWriteUnknown)
|
throw CocoaError.error(CocoaError.Code.fileWriteUnknown)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Play sound (sms_alert_note.caf) to indicate start of recording
|
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default, options: [])
|
||||||
AudioServicesPlayAlertSound(SystemSoundID(4097))
|
try AVAudioSession.sharedInstance().setActive(true)
|
||||||
|
|
||||||
ExtAudioFileSetProperty(fileRef, kExtAudioFileProperty_ClientDataFormat, UInt32(MemoryLayout<AudioStreamBasicDescription>.size), inFormat.streamDescription)
|
ExtAudioFileSetProperty(fileRef, kExtAudioFileProperty_ClientDataFormat, UInt32(MemoryLayout<AudioStreamBasicDescription>.size), inFormat.streamDescription)
|
||||||
|
|
||||||
@ -114,6 +111,7 @@ class Recorder {
|
|||||||
self.engine.inputNode.removeTap(onBus: 0)
|
self.engine.inputNode.removeTap(onBus: 0)
|
||||||
self.request.endAudio()
|
self.request.endAudio()
|
||||||
self.recognitionTask?.cancel()
|
self.recognitionTask?.cancel()
|
||||||
|
try? AVAudioSession.sharedInstance().setActive(false)
|
||||||
|
|
||||||
if let fileRef = self.fileRef {
|
if let fileRef = self.fileRef {
|
||||||
ExtAudioFileDispose(fileRef)
|
ExtAudioFileDispose(fileRef)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user