Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@ Pods
fastlane/report.xml
Construct.app.dSYM.zip
Construct.ipa

# Firebase
App/GoogleService-Info.plist

24 changes: 10 additions & 14 deletions App/App/App/ConstructApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
}
}
Expand Down
39 changes: 12 additions & 27 deletions App/App/App/CrashReporter.swift
Original file line number Diff line number Diff line change
@@ -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)
}
)
}
2 changes: 1 addition & 1 deletion App/App/App/Environment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ extension Environment {
return UIGraphicsGetImageFromCurrentImageContext()
},
diceLog: DiceLogPublisher(),
crashReporter: CrashReporter.appCenter,
crashReporter: CrashReporter.firebase,
mechMuse: .live(db: database)
)
}
Expand Down
34 changes: 12 additions & 22 deletions App/App/Settings/Fixtures/software_licenses.md
Original file line number Diff line number Diff line change
@@ -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

Expand Down
74 changes: 39 additions & 35 deletions App/Construct.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand Down Expand Up @@ -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 */; };
Expand Down Expand Up @@ -216,8 +217,9 @@
E90FB9FD25E946E90026191A /* AddCombatantReferenceItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddCombatantReferenceItemView.swift; sourceTree = "<group>"; };
E9121E2825FA75D50048BE32 /* FloatingDiceRollerViewState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingDiceRollerViewState.swift; sourceTree = "<group>"; };
E91885CC23944A3F0094EC87 /* ddb_bass.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ddb_bass.json; sourceTree = "<group>"; };
E91885CE239674DB0094EC87 /* Construct.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Construct.entitlements; sourceTree = "<group>"; };
E91B857E23DA3552009AF6D7 /* software_licenses.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = software_licenses.md; sourceTree = "<group>"; };
E91885CE239674DB0094EC87 /* Construct.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Construct.entitlements; sourceTree = "<group>"; };
F1F1F1F12500000000000000 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
E91B857E23DA3552009AF6D7 /* software_licenses.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = software_licenses.md; sourceTree = "<group>"; };
E91C167A2402DF3E004B5C85 /* SheetNavigationContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SheetNavigationContainer.swift; sourceTree = "<group>"; };
E91C167C2405C5BB004B5C85 /* SafariView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariView.swift; sourceTree = "<group>"; };
E91CCC862615D21B00CB0527 /* AppStoreScreenshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppStoreScreenshotTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -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 */,
Expand All @@ -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 */,
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -817,8 +820,8 @@
packageProductDependencies = (
E905E0BB246D83B800698C0A /* ComposableArchitecture */,
E93FA1C924EC5B7F007441BF /* Parma */,
E9869F732520A17A0098A166 /* AppCenterAnalytics */,
E9869F752520A17A0098A166 /* AppCenterCrashes */,
E9869F732520A17A0098A166 /* FirebaseAnalytics */,
E9869F752520A17A0098A166 /* FirebaseCrashlytics */,
E9869F7C2520A64B0098A166 /* GRDB */,
E991F89C2545A791006CE8E8 /* Introspect */,
E91CCC822614C4D200CB0527 /* Tagged */,
Expand Down Expand Up @@ -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" */,
Expand All @@ -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 */,
);
Expand Down Expand Up @@ -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";
Expand Down Expand Up @@ -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" */;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions App/GoogleService-Info.example.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?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">
<!-- Replace this file with your own GoogleService-Info.plist downloaded from the Firebase console. -->
</plist>
2 changes: 0 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -217,7 +216,6 @@ PLATFORMS

DEPENDENCIES
fastlane
fastlane-plugin-appcenter
xcode-install

BUNDLED WITH
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Loading
Loading