Add Firebase Crashlytics for error reporting
This commit is contained in:
parent
6896b7d9e6
commit
8c1239926b
6 changed files with 267 additions and 6 deletions
|
@ -39,6 +39,10 @@
|
||||||
801D08CE275F189E00931465 /* RecurringTransactionsRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 801D08CD275F189E00931465 /* RecurringTransactionsRepository.swift */; };
|
801D08CE275F189E00931465 /* RecurringTransactionsRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 801D08CD275F189E00931465 /* RecurringTransactionsRepository.swift */; };
|
||||||
801D08D2275FB7DE00931465 /* RecurringTransactionDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 801D08D1275FB7DE00931465 /* RecurringTransactionDetailsView.swift */; };
|
801D08D2275FB7DE00931465 /* RecurringTransactionDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 801D08D1275FB7DE00931465 /* RecurringTransactionDetailsView.swift */; };
|
||||||
802161D0277647920075761A /* AsyncObservableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 802161CF277647920075761A /* AsyncObservableObject.swift */; };
|
802161D0277647920075761A /* AsyncObservableObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 802161CF277647920075761A /* AsyncObservableObject.swift */; };
|
||||||
|
8043704028CBEC6800F229F9 /* FirebaseAnalyticsWithoutAdIdSupport in Frameworks */ = {isa = PBXBuildFile; productRef = 8043703F28CBEC6800F229F9 /* FirebaseAnalyticsWithoutAdIdSupport */; };
|
||||||
|
8043704228CBEC6800F229F9 /* FirebaseCrashlytics in Frameworks */ = {isa = PBXBuildFile; productRef = 8043704128CBEC6800F229F9 /* FirebaseCrashlytics */; };
|
||||||
|
8043704528CBEDF400F229F9 /* ErrorReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8043704428CBEDF400F229F9 /* ErrorReporter.swift */; };
|
||||||
|
8043704728CBF16600F229F9 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 8043704628CBF16600F229F9 /* GoogleService-Info.plist */; };
|
||||||
8043EB84271F26ED00498E73 /* CategoryDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8043EB83271F26ED00498E73 /* CategoryDetailsView.swift */; };
|
8043EB84271F26ED00498E73 /* CategoryDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8043EB83271F26ED00498E73 /* CategoryDetailsView.swift */; };
|
||||||
8044BA3927828E9D009A78D4 /* CategoryDataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8044BA3827828E9D009A78D4 /* CategoryDataStore.swift */; };
|
8044BA3927828E9D009A78D4 /* CategoryDataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8044BA3827828E9D009A78D4 /* CategoryDataStore.swift */; };
|
||||||
8044BA3B2784B659009A78D4 /* TransactionDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8044BA3A2784B659009A78D4 /* TransactionDetails.swift */; };
|
8044BA3B2784B659009A78D4 /* TransactionDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8044BA3A2784B659009A78D4 /* TransactionDetails.swift */; };
|
||||||
|
@ -136,6 +140,8 @@
|
||||||
801D08D1275FB7DE00931465 /* RecurringTransactionDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecurringTransactionDetailsView.swift; sourceTree = "<group>"; };
|
801D08D1275FB7DE00931465 /* RecurringTransactionDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecurringTransactionDetailsView.swift; sourceTree = "<group>"; };
|
||||||
802161CF277647920075761A /* AsyncObservableObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncObservableObject.swift; sourceTree = "<group>"; };
|
802161CF277647920075761A /* AsyncObservableObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncObservableObject.swift; sourceTree = "<group>"; };
|
||||||
8021EFAB280A0FA100043F18 /* TwigsCore */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = TwigsCore; path = ../TwigsCore; sourceTree = "<group>"; };
|
8021EFAB280A0FA100043F18 /* TwigsCore */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = TwigsCore; path = ../TwigsCore; sourceTree = "<group>"; };
|
||||||
|
8043704428CBEDF400F229F9 /* ErrorReporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorReporter.swift; sourceTree = "<group>"; };
|
||||||
|
8043704628CBF16600F229F9 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "../../../Downloads/GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||||
8043EB83271F26ED00498E73 /* CategoryDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryDetailsView.swift; sourceTree = "<group>"; };
|
8043EB83271F26ED00498E73 /* CategoryDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryDetailsView.swift; sourceTree = "<group>"; };
|
||||||
8044BA3827828E9D009A78D4 /* CategoryDataStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryDataStore.swift; sourceTree = "<group>"; };
|
8044BA3827828E9D009A78D4 /* CategoryDataStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryDataStore.swift; sourceTree = "<group>"; };
|
||||||
8044BA3A2784B659009A78D4 /* TransactionDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionDetails.swift; sourceTree = "<group>"; };
|
8044BA3A2784B659009A78D4 /* TransactionDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionDetails.swift; sourceTree = "<group>"; };
|
||||||
|
@ -168,7 +174,9 @@
|
||||||
files = (
|
files = (
|
||||||
80D06DD1288C817800B50467 /* TwigsCore in Frameworks */,
|
80D06DD1288C817800B50467 /* TwigsCore in Frameworks */,
|
||||||
8076A8522809FE99006B9DC9 /* Collections in Frameworks */,
|
8076A8522809FE99006B9DC9 /* Collections in Frameworks */,
|
||||||
|
8043704228CBEC6800F229F9 /* FirebaseCrashlytics in Frameworks */,
|
||||||
8076A84F2809FE8E006B9DC9 /* ArgumentParser in Frameworks */,
|
8076A84F2809FE8E006B9DC9 /* ArgumentParser in Frameworks */,
|
||||||
|
8043704028CBEC6800F229F9 /* FirebaseAnalyticsWithoutAdIdSupport in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -251,13 +259,13 @@
|
||||||
28AC94E1233C373900BFB70A = {
|
28AC94E1233C373900BFB70A = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
8005FD59277E623900E48B23 /* Frameworks */,
|
||||||
80DBED432774AE4F00CB0A88 /* Packages */,
|
80DBED432774AE4F00CB0A88 /* Packages */,
|
||||||
80A419EB2787C0A00090C515 /* twigs-cli */,
|
|
||||||
28AC94EB233C373900BFB70A /* Products */,
|
28AC94EB233C373900BFB70A /* Products */,
|
||||||
28AC94EC233C373900BFB70A /* Twigs */,
|
28AC94EC233C373900BFB70A /* Twigs */,
|
||||||
|
80A419EB2787C0A00090C515 /* twigs-cli */,
|
||||||
28AC9503233C373A00BFB70A /* TwigsTests */,
|
28AC9503233C373A00BFB70A /* TwigsTests */,
|
||||||
28AC950E233C373A00BFB70A /* TwigsUITests */,
|
28AC950E233C373A00BFB70A /* TwigsUITests */,
|
||||||
8005FD59277E623900E48B23 /* Frameworks */,
|
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
@ -275,6 +283,7 @@
|
||||||
28AC94EC233C373900BFB70A /* Twigs */ = {
|
28AC94EC233C373900BFB70A /* Twigs */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
8043704628CBF16600F229F9 /* GoogleService-Info.plist */,
|
||||||
282126A4235BCB7500072D52 /* Twigs.entitlements */,
|
282126A4235BCB7500072D52 /* Twigs.entitlements */,
|
||||||
28AC94FB233C373A00BFB70A /* Info.plist */,
|
28AC94FB233C373A00BFB70A /* Info.plist */,
|
||||||
28CE8B9423525F990072BC4C /* Extensions.swift */,
|
28CE8B9423525F990072BC4C /* Extensions.swift */,
|
||||||
|
@ -298,6 +307,7 @@
|
||||||
802161CF277647920075761A /* AsyncObservableObject.swift */,
|
802161CF277647920075761A /* AsyncObservableObject.swift */,
|
||||||
800DFC2B277FF47A00EDCE9B /* AsyncData.swift */,
|
800DFC2B277FF47A00EDCE9B /* AsyncData.swift */,
|
||||||
80D2CE192833448500EDD6C2 /* DataStore.swift */,
|
80D2CE192833448500EDD6C2 /* DataStore.swift */,
|
||||||
|
8043704428CBEDF400F229F9 /* ErrorReporter.swift */,
|
||||||
);
|
);
|
||||||
path = Twigs;
|
path = Twigs;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -404,6 +414,7 @@
|
||||||
28AC94E6233C373900BFB70A /* Sources */,
|
28AC94E6233C373900BFB70A /* Sources */,
|
||||||
28AC94E7233C373900BFB70A /* Frameworks */,
|
28AC94E7233C373900BFB70A /* Frameworks */,
|
||||||
28AC94E8233C373900BFB70A /* Resources */,
|
28AC94E8233C373900BFB70A /* Resources */,
|
||||||
|
8043704328CBED4000F229F9 /* ShellScript */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
|
@ -414,6 +425,8 @@
|
||||||
8076A84E2809FE8E006B9DC9 /* ArgumentParser */,
|
8076A84E2809FE8E006B9DC9 /* ArgumentParser */,
|
||||||
8076A8512809FE99006B9DC9 /* Collections */,
|
8076A8512809FE99006B9DC9 /* Collections */,
|
||||||
80D06DD0288C817800B50467 /* TwigsCore */,
|
80D06DD0288C817800B50467 /* TwigsCore */,
|
||||||
|
8043703F28CBEC6800F229F9 /* FirebaseAnalyticsWithoutAdIdSupport */,
|
||||||
|
8043704128CBEC6800F229F9 /* FirebaseCrashlytics */,
|
||||||
);
|
);
|
||||||
productName = Budget;
|
productName = Budget;
|
||||||
productReference = 28AC94EA233C373900BFB70A /* Twigs.app */;
|
productReference = 28AC94EA233C373900BFB70A /* Twigs.app */;
|
||||||
|
@ -517,6 +530,7 @@
|
||||||
8076A84A2809FE56006B9DC9 /* XCRemoteSwiftPackageReference "swift-argument-parser" */,
|
8076A84A2809FE56006B9DC9 /* XCRemoteSwiftPackageReference "swift-argument-parser" */,
|
||||||
8076A84D2809FE8D006B9DC9 /* XCRemoteSwiftPackageReference "swift-argument-parser" */,
|
8076A84D2809FE8D006B9DC9 /* XCRemoteSwiftPackageReference "swift-argument-parser" */,
|
||||||
8076A8502809FE99006B9DC9 /* XCRemoteSwiftPackageReference "swift-collections" */,
|
8076A8502809FE99006B9DC9 /* XCRemoteSwiftPackageReference "swift-collections" */,
|
||||||
|
8043703E28CBEC6800F229F9 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
|
||||||
);
|
);
|
||||||
productRefGroup = 28AC94EB233C373900BFB70A /* Products */;
|
productRefGroup = 28AC94EB233C373900BFB70A /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
|
@ -537,6 +551,7 @@
|
||||||
files = (
|
files = (
|
||||||
28AC94FA233C373A00BFB70A /* LaunchScreen.storyboard in Resources */,
|
28AC94FA233C373A00BFB70A /* LaunchScreen.storyboard in Resources */,
|
||||||
28AC951F233C381C00BFB70A /* Localizable.strings in Resources */,
|
28AC951F233C381C00BFB70A /* Localizable.strings in Resources */,
|
||||||
|
8043704728CBF16600F229F9 /* GoogleService-Info.plist in Resources */,
|
||||||
28AC94F7233C373A00BFB70A /* Preview Assets.xcassets in Resources */,
|
28AC94F7233C373A00BFB70A /* Preview Assets.xcassets in Resources */,
|
||||||
28AC94F4233C373A00BFB70A /* Assets.xcassets in Resources */,
|
28AC94F4233C373A00BFB70A /* Assets.xcassets in Resources */,
|
||||||
);
|
);
|
||||||
|
@ -558,6 +573,28 @@
|
||||||
};
|
};
|
||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
|
8043704328CBED4000F229F9 /* ShellScript */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}",
|
||||||
|
"$(SRCROOT)/newInputFile",
|
||||||
|
);
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n\"${BUILD_DIR%/Build/*}/SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/run\"\n";
|
||||||
|
};
|
||||||
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
28AC94E6233C373900BFB70A /* Sources */ = {
|
28AC94E6233C373900BFB70A /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
|
@ -604,6 +641,7 @@
|
||||||
284102302342D97300EAFA29 /* BudgetListsView.swift in Sources */,
|
284102302342D97300EAFA29 /* BudgetListsView.swift in Sources */,
|
||||||
282126BD235CDE1400072D52 /* ProgressView.swift in Sources */,
|
282126BD235CDE1400072D52 /* ProgressView.swift in Sources */,
|
||||||
806C7850272B700B00FA1375 /* TwigsApp.swift in Sources */,
|
806C7850272B700B00FA1375 /* TwigsApp.swift in Sources */,
|
||||||
|
8043704528CBEDF400F229F9 /* ErrorReporter.swift in Sources */,
|
||||||
808CA1A928355B30002EDD59 /* BudgetFormView.swift in Sources */,
|
808CA1A928355B30002EDD59 /* BudgetFormView.swift in Sources */,
|
||||||
80AF7A982835ED3B009565C6 /* RecurringTransactionFormView.swift in Sources */,
|
80AF7A982835ED3B009565C6 /* RecurringTransactionFormView.swift in Sources */,
|
||||||
28CE8B9523525F990072BC4C /* Extensions.swift in Sources */,
|
28CE8B9523525F990072BC4C /* Extensions.swift in Sources */,
|
||||||
|
@ -800,7 +838,8 @@
|
||||||
CODE_SIGN_ENTITLEMENTS = Twigs/Twigs.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Twigs/Twigs.entitlements;
|
||||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 18;
|
CURRENT_PROJECT_VERSION = 19;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES;
|
DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"Twigs/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"Twigs/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = 9Z6DE6KNJ9;
|
DEVELOPMENT_TEAM = 9Z6DE6KNJ9;
|
||||||
|
@ -829,7 +868,7 @@
|
||||||
CODE_SIGN_ENTITLEMENTS = Twigs/Twigs.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Twigs/Twigs.entitlements;
|
||||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 18;
|
CURRENT_PROJECT_VERSION = 19;
|
||||||
DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES;
|
DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"Twigs/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"Twigs/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = 9Z6DE6KNJ9;
|
DEVELOPMENT_TEAM = 9Z6DE6KNJ9;
|
||||||
|
@ -1014,6 +1053,14 @@
|
||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
|
|
||||||
/* Begin XCRemoteSwiftPackageReference section */
|
/* Begin XCRemoteSwiftPackageReference section */
|
||||||
|
8043703E28CBEC6800F229F9 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
|
||||||
|
isa = XCRemoteSwiftPackageReference;
|
||||||
|
repositoryURL = "https://github.com/firebase/firebase-ios-sdk";
|
||||||
|
requirement = {
|
||||||
|
kind = upToNextMajorVersion;
|
||||||
|
minimumVersion = 9.0.0;
|
||||||
|
};
|
||||||
|
};
|
||||||
8076A84A2809FE56006B9DC9 /* XCRemoteSwiftPackageReference "swift-argument-parser" */ = {
|
8076A84A2809FE56006B9DC9 /* XCRemoteSwiftPackageReference "swift-argument-parser" */ = {
|
||||||
isa = XCRemoteSwiftPackageReference;
|
isa = XCRemoteSwiftPackageReference;
|
||||||
repositoryURL = "https://github.com/apple/swift-argument-parser.git";
|
repositoryURL = "https://github.com/apple/swift-argument-parser.git";
|
||||||
|
@ -1057,6 +1104,16 @@
|
||||||
/* End XCRemoteSwiftPackageReference section */
|
/* End XCRemoteSwiftPackageReference section */
|
||||||
|
|
||||||
/* Begin XCSwiftPackageProductDependency section */
|
/* Begin XCSwiftPackageProductDependency section */
|
||||||
|
8043703F28CBEC6800F229F9 /* FirebaseAnalyticsWithoutAdIdSupport */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = 8043703E28CBEC6800F229F9 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
|
||||||
|
productName = FirebaseAnalyticsWithoutAdIdSupport;
|
||||||
|
};
|
||||||
|
8043704128CBEC6800F229F9 /* FirebaseCrashlytics */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = 8043703E28CBEC6800F229F9 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
|
||||||
|
productName = FirebaseCrashlytics;
|
||||||
|
};
|
||||||
8076A84E2809FE8E006B9DC9 /* ArgumentParser */ = {
|
8076A84E2809FE8E006B9DC9 /* ArgumentParser */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = 80A419F12787C13E0090C515 /* XCRemoteSwiftPackageReference "swift-argument-parser" */;
|
package = 80A419F12787C13E0090C515 /* XCRemoteSwiftPackageReference "swift-argument-parser" */;
|
||||||
|
|
|
@ -1,6 +1,105 @@
|
||||||
{
|
{
|
||||||
"object": {
|
"object": {
|
||||||
"pins": [
|
"pins": [
|
||||||
|
{
|
||||||
|
"package": "abseil",
|
||||||
|
"repositoryURL": "https://github.com/firebase/abseil-cpp-SwiftPM.git",
|
||||||
|
"state": {
|
||||||
|
"branch": null,
|
||||||
|
"revision": "583de9bd60f66b40e78d08599cc92036c2e7e4e1",
|
||||||
|
"version": "0.20220203.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "BoringSSL-GRPC",
|
||||||
|
"repositoryURL": "https://github.com/firebase/boringssl-SwiftPM.git",
|
||||||
|
"state": {
|
||||||
|
"branch": null,
|
||||||
|
"revision": "dd3eda2b05a3f459fc3073695ad1b28659066eab",
|
||||||
|
"version": "0.9.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "Firebase",
|
||||||
|
"repositoryURL": "https://github.com/firebase/firebase-ios-sdk",
|
||||||
|
"state": {
|
||||||
|
"branch": null,
|
||||||
|
"revision": "7f31a43f8c49bd4a1723bc9fecdfaa4411dd9f36",
|
||||||
|
"version": "9.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "GoogleAppMeasurement",
|
||||||
|
"repositoryURL": "https://github.com/google/GoogleAppMeasurement.git",
|
||||||
|
"state": {
|
||||||
|
"branch": null,
|
||||||
|
"revision": "f54f60d0164d887e1174fa51ab2efe48a8e9d178",
|
||||||
|
"version": "9.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "GoogleDataTransport",
|
||||||
|
"repositoryURL": "https://github.com/google/GoogleDataTransport.git",
|
||||||
|
"state": {
|
||||||
|
"branch": null,
|
||||||
|
"revision": "5056b15c5acbb90cd214fe4d6138bdf5a740e5a8",
|
||||||
|
"version": "9.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "GoogleUtilities",
|
||||||
|
"repositoryURL": "https://github.com/google/GoogleUtilities.git",
|
||||||
|
"state": {
|
||||||
|
"branch": null,
|
||||||
|
"revision": "f4abe56ce62a779e64b525eb133c8fc2a84bbc1f",
|
||||||
|
"version": "7.7.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "gRPC",
|
||||||
|
"repositoryURL": "https://github.com/grpc/grpc-ios.git",
|
||||||
|
"state": {
|
||||||
|
"branch": null,
|
||||||
|
"revision": "8440b914756e0d26d4f4d054a1c1581daedfc5b6",
|
||||||
|
"version": "1.44.3-grpc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "GTMSessionFetcher",
|
||||||
|
"repositoryURL": "https://github.com/google/gtm-session-fetcher.git",
|
||||||
|
"state": {
|
||||||
|
"branch": null,
|
||||||
|
"revision": "19605024d59eaefdb1f6a2cb11ebe75df4421126",
|
||||||
|
"version": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "leveldb",
|
||||||
|
"repositoryURL": "https://github.com/firebase/leveldb.git",
|
||||||
|
"state": {
|
||||||
|
"branch": null,
|
||||||
|
"revision": "0706abcc6b0bd9cedfbb015ba840e4a780b5159b",
|
||||||
|
"version": "1.22.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "nanopb",
|
||||||
|
"repositoryURL": "https://github.com/firebase/nanopb.git",
|
||||||
|
"state": {
|
||||||
|
"branch": null,
|
||||||
|
"revision": "819d0a2173aff699fb8c364b6fb906f7cdb1a692",
|
||||||
|
"version": "2.30909.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "Promises",
|
||||||
|
"repositoryURL": "https://github.com/google/promises.git",
|
||||||
|
"state": {
|
||||||
|
"branch": null,
|
||||||
|
"revision": "3e4e743631e86c8c70dbc6efdc7beaa6e90fd3bb",
|
||||||
|
"version": "2.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"package": "swift-argument-parser",
|
"package": "swift-argument-parser",
|
||||||
"repositoryURL": "https://github.com/apple/swift-argument-parser.git",
|
"repositoryURL": "https://github.com/apple/swift-argument-parser.git",
|
||||||
|
@ -18,6 +117,15 @@
|
||||||
"revision": "48254824bb4248676bf7ce56014ff57b142b77eb",
|
"revision": "48254824bb4248676bf7ce56014ff57b142b77eb",
|
||||||
"version": "1.0.2"
|
"version": "1.0.2"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "SwiftProtobuf",
|
||||||
|
"repositoryURL": "https://github.com/apple/swift-protobuf.git",
|
||||||
|
"state": {
|
||||||
|
"branch": null,
|
||||||
|
"revision": "b8230909dedc640294d7324d37f4c91ad3dcf177",
|
||||||
|
"version": "1.20.1"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -16,6 +16,7 @@ private let LAST_BUDGET = "LAST_BUDGET"
|
||||||
@MainActor
|
@MainActor
|
||||||
class DataStore : ObservableObject {
|
class DataStore : ObservableObject {
|
||||||
let apiService: TwigsApiService
|
let apiService: TwigsApiService
|
||||||
|
let errorReporter: ErrorReporter
|
||||||
@Published var budgets: AsyncData<[Budget]> = .empty
|
@Published var budgets: AsyncData<[Budget]> = .empty
|
||||||
@Published var budget: AsyncData<Budget> = .empty {
|
@Published var budget: AsyncData<Budget> = .empty {
|
||||||
didSet {
|
didSet {
|
||||||
|
@ -66,9 +67,11 @@ class DataStore : ObservableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
init(
|
init(
|
||||||
_ apiService: TwigsApiService
|
_ apiService: TwigsApiService,
|
||||||
|
errorReporter: ErrorReporter = LoggingErrorReporter()
|
||||||
) {
|
) {
|
||||||
self.apiService = apiService
|
self.apiService = apiService
|
||||||
|
self.errorReporter = errorReporter
|
||||||
self.baseUrl = UserDefaults.standard.string(forKey: KEY_BASE_URL) ?? ""
|
self.baseUrl = UserDefaults.standard.string(forKey: KEY_BASE_URL) ?? ""
|
||||||
self.apiService.baseUrl = baseUrl
|
self.apiService.baseUrl = baseUrl
|
||||||
self.token = UserDefaults.standard.string(forKey: KEY_TOKEN)
|
self.token = UserDefaults.standard.string(forKey: KEY_TOKEN)
|
||||||
|
@ -95,6 +98,7 @@ class DataStore : ObservableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
|
self.errorReporter.reportError(error: error)
|
||||||
self.budgets = .error(error)
|
self.budgets = .error(error)
|
||||||
showBudgetSelection = true
|
showBudgetSelection = true
|
||||||
}
|
}
|
||||||
|
@ -120,6 +124,7 @@ class DataStore : ObservableObject {
|
||||||
self.budgets = .success(updatedBudgets.sorted(by: { $0.name < $1.name }))
|
self.budgets = .success(updatedBudgets.sorted(by: { $0.name < $1.name }))
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
|
self.errorReporter.reportError(error: error)
|
||||||
self.budget = .error(error, budget)
|
self.budget = .error(error, budget)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,6 +141,7 @@ class DataStore : ObservableObject {
|
||||||
self.budgets = .success(budgets.filter(withoutId: budget.id))
|
self.budgets = .success(budgets.filter(withoutId: budget.id))
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
|
self.errorReporter.reportError(error: error)
|
||||||
self.budget = .error(error, budget)
|
self.budget = .error(error, budget)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,6 +194,7 @@ class DataStore : ObservableObject {
|
||||||
}
|
}
|
||||||
self.overview = .success(budgetOverview)
|
self.overview = .success(budgetOverview)
|
||||||
} catch {
|
} catch {
|
||||||
|
self.errorReporter.reportError(error: error)
|
||||||
self.overview = .error(error)
|
self.overview = .error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,6 +248,7 @@ class DataStore : ObservableObject {
|
||||||
let categories = try await apiService.getCategories(budgetId: budgetId, expense: expense, archived: archived, count: count, page: page)
|
let categories = try await apiService.getCategories(budgetId: budgetId, expense: expense, archived: archived, count: count, page: page)
|
||||||
self.categories = .success(categories)
|
self.categories = .success(categories)
|
||||||
} catch {
|
} catch {
|
||||||
|
self.errorReporter.reportError(error: error)
|
||||||
self.categories = .error(error)
|
self.categories = .error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,6 +270,7 @@ class DataStore : ObservableObject {
|
||||||
self.categories = .success(updatedCategories.sorted(by: { $0.title < $1.title }))
|
self.categories = .success(updatedCategories.sorted(by: { $0.title < $1.title }))
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
|
self.errorReporter.reportError(error: error)
|
||||||
self.category = .error(error, category)
|
self.category = .error(error, category)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -276,6 +285,7 @@ class DataStore : ObservableObject {
|
||||||
self.categories = .success(categories.filter(withoutId: category.id))
|
self.categories = .success(categories.filter(withoutId: category.id))
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
|
self.errorReporter.reportError(error: error)
|
||||||
self.category = .error(error, category)
|
self.category = .error(error, category)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -336,6 +346,7 @@ class DataStore : ObservableObject {
|
||||||
}
|
}
|
||||||
self.recurringTransactions = .success(recurringTransactions)
|
self.recurringTransactions = .success(recurringTransactions)
|
||||||
} catch {
|
} catch {
|
||||||
|
self.errorReporter.reportError(error: error)
|
||||||
self.recurringTransactions = .error(error)
|
self.recurringTransactions = .error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -381,6 +392,7 @@ class DataStore : ObservableObject {
|
||||||
}
|
}
|
||||||
await self.getRecurringTransactions()
|
await self.getRecurringTransactions()
|
||||||
} catch {
|
} catch {
|
||||||
|
self.errorReporter.reportError(error: error)
|
||||||
self.recurringTransactions = .error(error)
|
self.recurringTransactions = .error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -392,6 +404,7 @@ class DataStore : ObservableObject {
|
||||||
self.recurringTransaction = .empty
|
self.recurringTransaction = .empty
|
||||||
await self.getRecurringTransactions()
|
await self.getRecurringTransactions()
|
||||||
} catch {
|
} catch {
|
||||||
|
self.errorReporter.reportError(error: error)
|
||||||
self.recurringTransaction = .error(error, transaction)
|
self.recurringTransaction = .error(error, transaction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -436,6 +449,7 @@ class DataStore : ObservableObject {
|
||||||
let groupedTransactions = OrderedDictionary<String,[Transaction]>(grouping: transactions, by: { $0.date.toLocaleString() })
|
let groupedTransactions = OrderedDictionary<String,[Transaction]>(grouping: transactions, by: { $0.date.toLocaleString() })
|
||||||
self.transactions = .success(groupedTransactions)
|
self.transactions = .success(groupedTransactions)
|
||||||
} catch {
|
} catch {
|
||||||
|
self.errorReporter.reportError(error: error)
|
||||||
self.transactions = .error(error)
|
self.transactions = .error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -456,6 +470,7 @@ class DataStore : ObservableObject {
|
||||||
}
|
}
|
||||||
await getTransactions()
|
await getTransactions()
|
||||||
} catch {
|
} catch {
|
||||||
|
self.errorReporter.reportError(error: error)
|
||||||
self.transaction = .error(error, transaction)
|
self.transaction = .error(error, transaction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -467,6 +482,7 @@ class DataStore : ObservableObject {
|
||||||
self.transaction = .empty
|
self.transaction = .empty
|
||||||
await getTransactions()
|
await getTransactions()
|
||||||
} catch {
|
} catch {
|
||||||
|
self.errorReporter.reportError(error: error)
|
||||||
self.transaction = .error(error, transaction)
|
self.transaction = .error(error, transaction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -555,6 +571,7 @@ class DataStore : ObservableObject {
|
||||||
self.userId = response.userId
|
self.userId = response.userId
|
||||||
await self.loadProfile()
|
await self.loadProfile()
|
||||||
} catch {
|
} catch {
|
||||||
|
self.errorReporter.reportError(error: error)
|
||||||
switch error {
|
switch error {
|
||||||
case NetworkError.jsonParsingFailed(let jsonError):
|
case NetworkError.jsonParsingFailed(let jsonError):
|
||||||
print(jsonError.localizedDescription)
|
print(jsonError.localizedDescription)
|
||||||
|
@ -589,6 +606,7 @@ class DataStore : ObservableObject {
|
||||||
do {
|
do {
|
||||||
_ = try await apiService.register(username: username, email: email, password: password)
|
_ = try await apiService.register(username: username, email: email, password: password)
|
||||||
} catch {
|
} catch {
|
||||||
|
self.errorReporter.reportError(error: error)
|
||||||
switch error {
|
switch error {
|
||||||
case NetworkError.jsonParsingFailed(let jsonError):
|
case NetworkError.jsonParsingFailed(let jsonError):
|
||||||
print(jsonError.localizedDescription)
|
print(jsonError.localizedDescription)
|
||||||
|
@ -630,6 +648,7 @@ class DataStore : ObservableObject {
|
||||||
self.currentUser = .success(user)
|
self.currentUser = .success(user)
|
||||||
await getBudgets()
|
await getBudgets()
|
||||||
} catch {
|
} catch {
|
||||||
|
self.errorReporter.reportError(error: error)
|
||||||
self.currentUser = .error(error)
|
self.currentUser = .error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -644,6 +663,7 @@ class DataStore : ObservableObject {
|
||||||
self.currentUser = .success(updated)
|
self.currentUser = .success(updated)
|
||||||
return nil
|
return nil
|
||||||
} catch {
|
} catch {
|
||||||
|
self.errorReporter.reportError(error: error)
|
||||||
self.currentUser = .error(error, current)
|
self.currentUser = .error(error, current)
|
||||||
return .unavailable
|
return .unavailable
|
||||||
}
|
}
|
||||||
|
@ -662,6 +682,7 @@ class DataStore : ObservableObject {
|
||||||
self.currentUser = .success(updated)
|
self.currentUser = .success(updated)
|
||||||
return nil
|
return nil
|
||||||
} catch {
|
} catch {
|
||||||
|
self.errorReporter.reportError(error: error)
|
||||||
self.currentUser = .error(error, current)
|
self.currentUser = .error(error, current)
|
||||||
return .unavailable
|
return .unavailable
|
||||||
}
|
}
|
||||||
|
@ -680,6 +701,7 @@ class DataStore : ObservableObject {
|
||||||
self.currentUser = .success(updated)
|
self.currentUser = .success(updated)
|
||||||
return nil
|
return nil
|
||||||
} catch {
|
} catch {
|
||||||
|
self.errorReporter.reportError(error: error)
|
||||||
self.currentUser = .error(error, current)
|
self.currentUser = .error(error, current)
|
||||||
return .unknown
|
return .unknown
|
||||||
}
|
}
|
||||||
|
@ -695,6 +717,7 @@ class DataStore : ObservableObject {
|
||||||
self.currentUser = .success(updated)
|
self.currentUser = .success(updated)
|
||||||
return true
|
return true
|
||||||
} catch {
|
} catch {
|
||||||
|
self.errorReporter.reportError(error: error)
|
||||||
self.currentUser = .error(error, current)
|
self.currentUser = .error(error, current)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -707,6 +730,7 @@ class DataStore : ObservableObject {
|
||||||
let user = try await self.apiService.getUser(id)
|
let user = try await self.apiService.getUser(id)
|
||||||
self.user = .success(user)
|
self.user = .success(user)
|
||||||
} catch {
|
} catch {
|
||||||
|
self.errorReporter.reportError(error: error)
|
||||||
self.currentUser = .error(error)
|
self.currentUser = .error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
26
Twigs/ErrorReporter.swift
Normal file
26
Twigs/ErrorReporter.swift
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
//
|
||||||
|
// ErrorReporter.swift
|
||||||
|
// Twigs
|
||||||
|
//
|
||||||
|
// Created by William Brawner on 9/9/22.
|
||||||
|
// Copyright © 2022 William Brawner. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import FirebaseCrashlytics
|
||||||
|
|
||||||
|
protocol ErrorReporter {
|
||||||
|
func reportError(error: Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoggingErrorReporter: ErrorReporter {
|
||||||
|
func reportError(error: Error) {
|
||||||
|
print(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FirebaseErrorReporter: ErrorReporter {
|
||||||
|
func reportError(error: Error) {
|
||||||
|
Crashlytics.crashlytics().record(error: error)
|
||||||
|
}
|
||||||
|
}
|
36
Twigs/GoogleService-Info.plist
Normal file
36
Twigs/GoogleService-Info.plist
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CLIENT_ID</key>
|
||||||
|
<string>527070722499-8qtkq1oqkveapng949atmdt7l38r75ps.apps.googleusercontent.com</string>
|
||||||
|
<key>REVERSED_CLIENT_ID</key>
|
||||||
|
<string>com.googleusercontent.apps.527070722499-8qtkq1oqkveapng949atmdt7l38r75ps</string>
|
||||||
|
<key>API_KEY</key>
|
||||||
|
<string>AIzaSyDzEcz1sz65JXpujOfFrRqUG2kD_tooA50</string>
|
||||||
|
<key>GCM_SENDER_ID</key>
|
||||||
|
<string>527070722499</string>
|
||||||
|
<key>PLIST_VERSION</key>
|
||||||
|
<string>1</string>
|
||||||
|
<key>BUNDLE_ID</key>
|
||||||
|
<string>com.wbrawner.projects.budget.ios</string>
|
||||||
|
<key>PROJECT_ID</key>
|
||||||
|
<string>budget-c7da5</string>
|
||||||
|
<key>STORAGE_BUCKET</key>
|
||||||
|
<string>budget-c7da5.appspot.com</string>
|
||||||
|
<key>IS_ADS_ENABLED</key>
|
||||||
|
<false></false>
|
||||||
|
<key>IS_ANALYTICS_ENABLED</key>
|
||||||
|
<false></false>
|
||||||
|
<key>IS_APPINVITE_ENABLED</key>
|
||||||
|
<true></true>
|
||||||
|
<key>IS_GCM_ENABLED</key>
|
||||||
|
<true></true>
|
||||||
|
<key>IS_SIGNIN_ENABLED</key>
|
||||||
|
<true></true>
|
||||||
|
<key>GOOGLE_APP_ID</key>
|
||||||
|
<string>1:527070722499:ios:0e0c4e20d30697df73e576</string>
|
||||||
|
<key>DATABASE_URL</key>
|
||||||
|
<string>https://budget-c7da5.firebaseio.com</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -6,16 +6,26 @@
|
||||||
// Copyright © 2021 William Brawner. All rights reserved.
|
// Copyright © 2021 William Brawner. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
import FirebaseCore
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import TwigsCore
|
import TwigsCore
|
||||||
|
|
||||||
|
class AppDelegate: NSObject, UIApplicationDelegate {
|
||||||
|
func application(_ application: UIApplication,
|
||||||
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
|
||||||
|
FirebaseApp.configure()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct MainView: View {
|
struct MainView: View {
|
||||||
|
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
|
||||||
@StateObject var dataStore: DataStore
|
@StateObject var dataStore: DataStore
|
||||||
let apiService: TwigsApiService
|
let apiService: TwigsApiService
|
||||||
|
|
||||||
init(_ apiService: TwigsApiService) {
|
init(_ apiService: TwigsApiService) {
|
||||||
self.apiService = apiService
|
self.apiService = apiService
|
||||||
self._dataStore = StateObject(wrappedValue: DataStore(apiService))
|
self._dataStore = StateObject(wrappedValue: DataStore(apiService, errorReporter: FirebaseErrorReporter()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
|
|
Loading…
Reference in a new issue