diff --git a/.gitignore b/.gitignore index cd87580..14dc67d 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,7 @@ Pods fastlane/report.xml Construct.app.dSYM.zip Construct.ipa + +# Firebase +App/GoogleService-Info.plist + diff --git a/App/App/App/ConstructApp.swift b/App/App/App/ConstructApp.swift index 0054b84..85b9d29 100644 --- a/App/App/App/ConstructApp.swift +++ b/App/App/App/ConstructApp.swift @@ -9,18 +9,16 @@ import SwiftUI import Combine import ComposableArchitecture -import AppCenter -import AppCenterAnalytics -import AppCenterCrashes +import FirebaseCore +import FirebaseAnalytics +import FirebaseCrashlytics import GameModels @main struct ConstructApp: App { init() { - AppCenter.start(withAppSecret: "72078370-4844-4ec2-a850-22a22dee0233", services: [ - Analytics.self, Crashes.self - ]) + FirebaseApp.configure() } @SceneBuilder @@ -198,16 +196,14 @@ struct ConstructView: View { } private func setUpCrashesUserConfirmationHandler() { - Crashes.userConfirmationHandler = { (errorReports: [ErrorReport]) in - if let preferences: Preferences = try? env.database.keyValueStore.get(Preferences.key), - preferences.errorReportingEnabled == true - { - // user consent has been given, send reports - return false + if let preferences: Preferences = try? env.database.keyValueStore.get(Preferences.key) { + Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(preferences.errorReportingEnabled == true) + if preferences.errorReportingEnabled != true { + ViewStore(store).send(.requestPresentation(.crashReportingPermissionAlert)) } - + } else { + Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(false) ViewStore(store).send(.requestPresentation(.crashReportingPermissionAlert)) - return true } } } diff --git a/App/App/App/CrashReporter.swift b/App/App/App/CrashReporter.swift index d568dd7..3e52d22 100644 --- a/App/App/App/CrashReporter.swift +++ b/App/App/App/CrashReporter.swift @@ -1,41 +1,26 @@ -// -// CrashReporter.swift -// Construct -// -// Created by Thomas Visser on 22/09/2022. -// Copyright © 2022 Thomas Visser. All rights reserved. -// - import Foundation -import AppCenterCrashes +import FirebaseCrashlytics import GameModels import Helpers extension CrashReporter { - static let appCenter = CrashReporter( + static let firebase = CrashReporter( registerUserPermission: { permission in switch permission { case .dontSend: - Crashes.notify(with: .dontSend) - case .send: - Crashes.notify(with: .send) - case .sendAlways: - Crashes.notify(with: .always) + Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(false) + case .send, .sendAlways: + Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true) } }, trackError: { report in - Crashes.trackException( - ExceptionModel( - // NSError.domain gives the fully qualified name of the Swift error type - withType: (report.error as NSError).domain, - exceptionMessage: String(describing: report.error), - stackTrace: Array(Thread.callStackSymbols[2...]) - ), - properties: report.properties, - attachments: report.attachments.map { name, text in - ErrorAttachmentLog(filename: name, attachmentText: text) - } - ) + for (key, value) in report.properties { + Crashlytics.crashlytics().setCustomValue(value, forKey: key) + } + for (name, text) in report.attachments { + Crashlytics.crashlytics().log("\(name): \(text)") + } + Crashlytics.crashlytics().record(error: report.error) } ) } diff --git a/App/App/App/Environment.swift b/App/App/App/Environment.swift index 64c9381..84b13b6 100644 --- a/App/App/App/Environment.swift +++ b/App/App/App/Environment.swift @@ -174,7 +174,7 @@ extension Environment { return UIGraphicsGetImageFromCurrentImageContext() }, diceLog: DiceLogPublisher(), - crashReporter: CrashReporter.appCenter, + crashReporter: CrashReporter.firebase, mechMuse: .live(db: database) ) } diff --git a/App/App/Settings/Fixtures/software_licenses.md b/App/App/Settings/Fixtures/software_licenses.md index 07594d2..ad45a2f 100644 --- a/App/App/Settings/Fixtures/software_licenses.md +++ b/App/App/Settings/Fixtures/software_licenses.md @@ -1,32 +1,22 @@ # Third-party software This application makes use of the following third party libraries: -## AppCenter -Visual Studio App Center SDK for Apple platforms +## Firebase +Firebase iOS SDK -Copyright (c) Microsoft Corporation +Copyright 2023 Google -All rights reserved. - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. + http://www.apache.org/licenses/LICENSE-2.0 -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. ## AsyncAlgorithms diff --git a/App/Construct.xcodeproj/project.pbxproj b/App/Construct.xcodeproj/project.pbxproj index f6030a9..a6ac93a 100644 --- a/App/Construct.xcodeproj/project.pbxproj +++ b/App/Construct.xcodeproj/project.pbxproj @@ -14,8 +14,9 @@ E90EFF412623220300F5443E /* DataSourceReaderParsersTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E90EFF402623220300F5443E /* DataSourceReaderParsersTest.swift */; }; E90FB9FE25E946E90026191A /* AddCombatantReferenceItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E90FB9FD25E946E90026191A /* AddCombatantReferenceItemView.swift */; }; E9121E2925FA75D50048BE32 /* FloatingDiceRollerViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9121E2825FA75D50048BE32 /* FloatingDiceRollerViewState.swift */; }; - E91885CD23944A3F0094EC87 /* ddb_bass.json in Resources */ = {isa = PBXBuildFile; fileRef = E91885CC23944A3F0094EC87 /* ddb_bass.json */; }; - E91B857F23DA355B009AF6D7 /* software_licenses.md in Resources */ = {isa = PBXBuildFile; fileRef = E91B857E23DA3552009AF6D7 /* software_licenses.md */; }; + E91885CD23944A3F0094EC87 /* ddb_bass.json in Resources */ = {isa = PBXBuildFile; fileRef = E91885CC23944A3F0094EC87 /* ddb_bass.json */; }; + F1F1F1F32500000000000000 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = F1F1F1F12500000000000000 /* GoogleService-Info.plist */; }; + E91B857F23DA355B009AF6D7 /* software_licenses.md in Resources */ = {isa = PBXBuildFile; fileRef = E91B857E23DA3552009AF6D7 /* software_licenses.md */; }; E91C167D2405C5BB004B5C85 /* SafariView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E91C167C2405C5BB004B5C85 /* SafariView.swift */; }; E91CCC832614C4D200CB0527 /* Tagged in Frameworks */ = {isa = PBXBuildFile; productRef = E91CCC822614C4D200CB0527 /* Tagged */; }; E91CCC872615D21B00CB0527 /* AppStoreScreenshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E91CCC862615D21B00CB0527 /* AppStoreScreenshotTests.swift */; }; @@ -101,8 +102,8 @@ E9819BE324852498005B898E /* CampaignBrowserContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9F56AC32350FA5D0085A72D /* CampaignBrowserContainerView.swift */; }; E9819BE4248524AA005B898E /* CampaignBrowseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9CFB31123505AF400CA0AF4 /* CampaignBrowseView.swift */; }; E9819BE52485252A005B898E /* SheetNavigationContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E91C167A2402DF3E004B5C85 /* SheetNavigationContainer.swift */; }; - E9869F742520A17A0098A166 /* AppCenterAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = E9869F732520A17A0098A166 /* AppCenterAnalytics */; }; - E9869F762520A17A0098A166 /* AppCenterCrashes in Frameworks */ = {isa = PBXBuildFile; productRef = E9869F752520A17A0098A166 /* AppCenterCrashes */; }; + E9869F742520A17A0098A166 /* FirebaseAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = E9869F732520A17A0098A166 /* FirebaseAnalytics */; }; + E9869F762520A17A0098A166 /* FirebaseCrashlytics in Frameworks */ = {isa = PBXBuildFile; productRef = E9869F752520A17A0098A166 /* FirebaseCrashlytics */; }; E9869F7D2520A64B0098A166 /* GRDB in Frameworks */ = {isa = PBXBuildFile; productRef = E9869F7C2520A64B0098A166 /* GRDB */; }; E9869F8D252203BA0098A166 /* TabNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9869F8C252203BA0098A166 /* TabNavigationView.swift */; }; E9869F91252203F40098A166 /* TabNavigationViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9869F90252203F40098A166 /* TabNavigationViewState.swift */; }; @@ -216,8 +217,9 @@ E90FB9FD25E946E90026191A /* AddCombatantReferenceItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddCombatantReferenceItemView.swift; sourceTree = ""; }; E9121E2825FA75D50048BE32 /* FloatingDiceRollerViewState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingDiceRollerViewState.swift; sourceTree = ""; }; E91885CC23944A3F0094EC87 /* ddb_bass.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ddb_bass.json; sourceTree = ""; }; - E91885CE239674DB0094EC87 /* Construct.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Construct.entitlements; sourceTree = ""; }; - E91B857E23DA3552009AF6D7 /* software_licenses.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = software_licenses.md; sourceTree = ""; }; + E91885CE239674DB0094EC87 /* Construct.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Construct.entitlements; sourceTree = ""; }; + F1F1F1F12500000000000000 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; + E91B857E23DA3552009AF6D7 /* software_licenses.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = software_licenses.md; sourceTree = ""; }; E91C167A2402DF3E004B5C85 /* SheetNavigationContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SheetNavigationContainer.swift; sourceTree = ""; }; E91C167C2405C5BB004B5C85 /* SafariView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariView.swift; sourceTree = ""; }; E91CCC862615D21B00CB0527 /* AppStoreScreenshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppStoreScreenshotTests.swift; sourceTree = ""; }; @@ -364,7 +366,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - E9869F742520A17A0098A166 /* AppCenterAnalytics in Frameworks */, + E9869F742520A17A0098A166 /* FirebaseAnalytics in Frameworks */, E99C930828B0189D00018518 /* Dice in Frameworks */, E91CCC832614C4D200CB0527 /* Tagged in Frameworks */, E991F89D2545A791006CE8E8 /* Introspect in Frameworks */, @@ -375,7 +377,7 @@ E9F1286D28E6D6130040C90C /* Persistence in Frameworks */, E99C930C28B0189D00018518 /* Helpers in Frameworks */, E9D1138B28AFBCA300CEF923 /* DiceRollerFeature in Frameworks */, - E9869F762520A17A0098A166 /* AppCenterCrashes in Frameworks */, + E9869F762520A17A0098A166 /* FirebaseCrashlytics in Frameworks */, E99C930E28B0189D00018518 /* SharedViews in Frameworks */, E93FA1CA24EC5B7F007441BF /* Parma in Frameworks */, E9BE1C4F28B524FF00D80464 /* DiceRollerInvocation in Frameworks */, @@ -618,10 +620,11 @@ }; E999896222A6B4F20067BA25 /* App */ = { isa = PBXGroup; - children = ( - E91885CE239674DB0094EC87 /* Construct.entitlements */, - E92A41E2240D2CCD009AF440 /* App */, - E91EB0B223EE089A00F40E46 /* Resources */, + children = ( + E91885CE239674DB0094EC87 /* Construct.entitlements */, + F1F1F1F12500000000000000 /* GoogleService-Info.plist */, + E92A41E2240D2CCD009AF440 /* App */, + E91EB0B223EE089A00F40E46 /* Resources */, E91B858223E43368009AF6D7 /* DiceRoller */, E96FC16423D3974200A12F1E /* Settings */, E999FBD7235DC66F000CCC8B /* Combatant */, @@ -817,8 +820,8 @@ packageProductDependencies = ( E905E0BB246D83B800698C0A /* ComposableArchitecture */, E93FA1C924EC5B7F007441BF /* Parma */, - E9869F732520A17A0098A166 /* AppCenterAnalytics */, - E9869F752520A17A0098A166 /* AppCenterCrashes */, + E9869F732520A17A0098A166 /* FirebaseAnalytics */, + E9869F752520A17A0098A166 /* FirebaseCrashlytics */, E9869F7C2520A64B0098A166 /* GRDB */, E991F89C2545A791006CE8E8 /* Introspect */, E91CCC822614C4D200CB0527 /* Tagged */, @@ -916,7 +919,7 @@ packageReferences = ( E905E0BA246D83B800698C0A /* XCRemoteSwiftPackageReference "swift-composable-architecture" */, E93FA1C824EC5B7F007441BF /* XCRemoteSwiftPackageReference "Parma" */, - E9869F6F2520A1320098A166 /* XCRemoteSwiftPackageReference "appcenter-sdk-apple" */, + E9869F6F2520A1320098A166 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */, E9869F7B2520A64B0098A166 /* XCRemoteSwiftPackageReference "GRDB.swift" */, E991F89B2545A791006CE8E8 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */, E91CCC812614C4D200CB0527 /* XCRemoteSwiftPackageReference "swift-tagged" */, @@ -941,8 +944,9 @@ files = ( E999897022A6B4F30067BA25 /* LaunchScreen.storyboard in Resources */, E91EB0B423EE08CB00F40E46 /* roll.ahap in Resources */, - E91B857F23DA355B009AF6D7 /* software_licenses.md in Resources */, - E999896D22A6B4F30067BA25 /* Preview Assets.xcassets in Resources */, + E91B857F23DA355B009AF6D7 /* software_licenses.md in Resources */, + F1F1F1F32500000000000000 /* GoogleService-Info.plist in Resources */, + E999896D22A6B4F30067BA25 /* Preview Assets.xcassets in Resources */, E999896A22A6B4F30067BA25 /* Assets.xcassets in Resources */, E96FC16923D3A5BE00A12F1E /* ogl.md in Resources */, ); @@ -1526,14 +1530,14 @@ minimumVersion = 2.0.0; }; }; - E9869F6F2520A1320098A166 /* XCRemoteSwiftPackageReference "appcenter-sdk-apple" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/microsoft/appcenter-sdk-apple.git"; - requirement = { - branch = master; - kind = branch; - }; - }; + E9869F6F2520A1320098A166 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/firebase/firebase-ios-sdk.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 11.0.0; + }; + }; E9869F7B2520A64B0098A166 /* XCRemoteSwiftPackageReference "GRDB.swift" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/Thomvis/GRDB.swift.git"; @@ -1589,16 +1593,16 @@ isa = XCSwiftPackageProductDependency; productName = Open5eAPI; }; - E9869F732520A17A0098A166 /* AppCenterAnalytics */ = { - isa = XCSwiftPackageProductDependency; - package = E9869F6F2520A1320098A166 /* XCRemoteSwiftPackageReference "appcenter-sdk-apple" */; - productName = AppCenterAnalytics; - }; - E9869F752520A17A0098A166 /* AppCenterCrashes */ = { - isa = XCSwiftPackageProductDependency; - package = E9869F6F2520A1320098A166 /* XCRemoteSwiftPackageReference "appcenter-sdk-apple" */; - productName = AppCenterCrashes; - }; + E9869F732520A17A0098A166 /* FirebaseAnalytics */ = { + isa = XCSwiftPackageProductDependency; + package = E9869F6F2520A1320098A166 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; + productName = FirebaseAnalytics; + }; + E9869F752520A17A0098A166 /* FirebaseCrashlytics */ = { + isa = XCSwiftPackageProductDependency; + package = E9869F6F2520A1320098A166 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; + productName = FirebaseCrashlytics; + }; E9869F7C2520A64B0098A166 /* GRDB */ = { isa = XCSwiftPackageProductDependency; package = E9869F7B2520A64B0098A166 /* XCRemoteSwiftPackageReference "GRDB.swift" */; diff --git a/App/Construct.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/App/Construct.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 765d924..5bc1e57 100644 --- a/App/Construct.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/App/Construct.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,12 +1,12 @@ { "pins" : [ { - "identity" : "appcenter-sdk-apple", + "identity" : "firebase-ios-sdk", "kind" : "remoteSourceControl", - "location" : "https://github.com/microsoft/appcenter-sdk-apple.git", + "location" : "https://github.com/firebase/firebase-ios-sdk.git", "state" : { - "branch" : "master", - "revision" : "f2bcbd9eba88e32d2de9ce9512c4c47eabbf27ca" + "revision" : "93d9c992a45ae30ff88fb7ba04403593f084f663", + "version" : "11.14.0" } }, { diff --git a/App/GoogleService-Info.example.plist b/App/GoogleService-Info.example.plist new file mode 100644 index 0000000..e619a26 --- /dev/null +++ b/App/GoogleService-Info.example.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/Gemfile.lock b/Gemfile.lock index 747f54c..e001b9f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -105,7 +105,6 @@ GEM xcodeproj (>= 1.13.0, < 2.0.0) xcpretty (~> 0.3.0) xcpretty-travis-formatter (>= 0.0.3) - fastlane-plugin-appcenter (1.11.0) gh_inspector (1.1.3) google-apis-androidpublisher_v3 (0.33.0) google-apis-core (>= 0.9.1, < 2.a) @@ -217,7 +216,6 @@ PLATFORMS DEPENDENCIES fastlane - fastlane-plugin-appcenter xcode-install BUNDLED WITH diff --git a/README.md b/README.md index b6f123e..ed50ee9 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,8 @@ The easiest way to use the app is by downloading it from the App Store. You can find an overview of Construct's features at [construct5e.app](https://www.construct5e.app). ### For developers -Download the project, open `Construct.xcodeproj` and run `Construct`. +Download the project, copy your `GoogleService-Info.plist` downloaded from the Firebase console to `App/GoogleService-Info.plist` and then open `Construct.xcodeproj`. +The real plist is intentionally git‑ignored. A sample `GoogleService-Info.example.plist` is included as a reference. #### Architecture overview Construct is built using SwiftUI and a reducer-based architecture implemented using [The Composable Architecture](https://github.com/pointfreeco/swift-composable-architecture) framework. The entire app's state is represented by the [AppState struct](https://github.com/Thomvis/Construct/blob/main/Construct/App/AppState.swift), a deeply nested data structure containing the top-level screens and any screen, sheet or popover opened from there. A [tight integration](https://github.com/Thomvis/Construct/blob/main/Construct/Foundation/Navigation.swift) between SwiftUI's NavigationLink and the app's state make programmatic navigation a breeze. diff --git a/fastlane/Fastfile b/fastlane/Fastfile index ef16163..9205b46 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -40,19 +40,6 @@ platform :ios do ) end - lane :update_appcenter_dsyms do - download_dsyms(version: "latest") - - lane_context[SharedValues::DSYM_PATHS].each do |dsym| - appcenter_upload( - owner_name: "thomas-visser-00ws", - owner_type: "user", # Default is user - set to organization for appcenter organizations - app_name: "Construct", - dsym: dsym, - upload_dsym_only: true - ) - end - end desc "Prepares the screenshots generated by the AppStoreScreenshotTests unit test case to be uploaded to the App Store" lane :prepare_app_store_screenshots do diff --git a/fastlane/Pluginfile b/fastlane/Pluginfile index 756bff8..f4b8ec7 100644 --- a/fastlane/Pluginfile +++ b/fastlane/Pluginfile @@ -2,4 +2,3 @@ # # Ensure this file is checked in to source control! -gem 'fastlane-plugin-appcenter' diff --git a/fastlane/README.md b/fastlane/README.md index 0d0365e..6e6adc2 100644 --- a/fastlane/README.md +++ b/fastlane/README.md @@ -31,13 +31,6 @@ Push a new beta build to TestFlight -### ios update_appcenter_dsyms - -```sh -[bundle exec] fastlane ios update_appcenter_dsyms -``` - - ### ios prepare_app_store_screenshots