Skip to content

Commit 552d251

Browse files
authored
Apple Push Notifications & Basic Web Data Viewers (#53)
v6.0.2 * web progress * detail data view * Web versions, APN support start * notification on client * 2% battery commit * 🙏 * why does this have to be hard * thank scouts button? * finish APNs and web thing
1 parent d023380 commit 552d251

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1659
-454
lines changed

.example.env

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ PASSKEY_RP_ID=localhost
55
TEAMS=766
66
EVENTS=CASJ,CASD,CABE
77
SEASONS=2024,2025
8-
APN_BUNDLE_ID=""
98
APN_KEY_ID=""
10-
APN_TEAM_ID=""
9+
APN_TEAM_ID=""
10+
APN_ENDPOINT="SANDBOX"

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pkg*
1010
Cargo.lock
1111
.env
1212
ssl/*.pem
13-
keys/*.p8
13+
ssl/*.p8
1414
.vscode*
1515
*.swiftpm/
1616
*.swiftpm/*

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "bear_tracks"
3-
version = "6.1.0"
3+
version = "6.0.2"
44
edition = "2021"
55
authors = ["Jayen Agrawal"]
66
description = "a scouting app for frc"
@@ -9,6 +9,7 @@ repository = "https://github.com/JayAgra/bearTracks/"
99
build = "build.rs"
1010

1111
[dependencies]
12+
a2 = "0.10.0"
1213
actix = "0.13.1"
1314
actix-files = "0.6.5"
1415
actix-governor = "0.5.0"

README.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@ a webapp for frc scouting<br><br>
33
![GitHub](https://img.shields.io/github/license/JayAgra/bearTracks) ![GitHub commit activity](https://img.shields.io/github/commit-activity/y/jayagra/bearTracks) ![GitHub last commit](https://img.shields.io/github/last-commit/jayagra/bearTracks)
44

55
## setup
6-
### script
7-
set up bearTracks using the simple shell script.
8-
```sh
9-
curl -fSsl "https://raw.githubusercontent.com/JayAgra/bearTracks/main/setup.sh" | sudo sh
10-
```
116
### environment variables
127
```
138
FRC_API_KEY
@@ -17,6 +12,8 @@ PASSKEY_RP_ID
1712
TEAMS
1813
EVENTS
1914
SEASONS
15+
APN_KEY_ID
16+
APN_TEAM_ID
2017
```
2118
+ **FRC_API_KEY** FRC API credentials, in base64. standard encoding (`username:token`), and omit the "Basic " occasionally prepended to the string. obtain a key: https://frc-events.firstinspires.org/services/API. (default: `NONE`)<br>
2219
+ **MY_TEAM** your team number (default: `766`)<br>
@@ -25,6 +22,8 @@ SEASONS
2522
+ **TEAMS** is a comma separated list of all teams registered to use this instance of the app<br>
2623
+ **EVENTS** is a comma separated list of all events the app should use<br>
2724
+ **SEASONS** is a comma separated list of all seasons this app has been used
25+
+ **APN_KEY_ID** the ID of the APN key in the ssl folder (filename APN.p8)
26+
+ **APN_TEAM_ID** the team ID of the APN key
2827
### ssl
2928
use cloudflare ssl in full strict mode. place certificate and key in `ssl/cert.pem` and `ssl/key.pem`.
3029
### running server
@@ -52,9 +51,9 @@ The clients are broken into 3 apps- Data, Scout, and Manage. Manage is intended
5251
| watchOS 9-11||||
5352
| visionOS 2 ||||
5453
| App Store ||||
55-
| Web (PWA) || ||
54+
| Web (PWA) || ||
5655

57-
<small>android users may use web</small>
56+
<small>android users may use web.<br>web data access is not as complete as iOS access.</small>
5857

5958
[Data iOS](https://apps.apple.com/app/beartracks-data/id6475752596)<br>
6059
[Data macOS](https://apps.apple.com/app/beartracks-data/id6475752596)<br>

data_auth.db

0 Bytes
Binary file not shown.

data_pit.db

0 Bytes
Binary file not shown.

ios/beartracks/bearTracks.xcodeproj/project.pbxproj

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
F51BC0C62BB71B2D009587C1 /* Stickers.xcstickers in Resources */ = {isa = PBXBuildFile; fileRef = F51BC0A02BB717D1009587C1 /* Stickers.xcstickers */; };
1212
F51BC0CF2BB71CB5009587C1 /* bearTracks Stickers.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = F51BC0B82BB71AF5009587C1 /* bearTracks Stickers.appex */; platformFilter = ios; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
1313
F532B0342D4BE6D900B7C127 /* RegionalPoints.swift in Sources */ = {isa = PBXBuildFile; fileRef = F532B0322D4BE6D900B7C127 /* RegionalPoints.swift */; };
14+
F5346CAC2D710D3400EBAC99 /* NotificationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5346CAA2D710D3400EBAC99 /* NotificationDelegate.swift */; };
1415
F535387A2BB4D03F00D15A15 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F54E76C52B527D97003C65A2 /* Assets.xcassets */; };
1516
F53F36422BB74B0A008F196B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F53F36412BB74B0A008F196B /* Assets.xcassets */; };
1617
F53F36452BB74B0A008F196B /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F53F36442BB74B0A008F196B /* Preview Assets.xcassets */; };
@@ -122,6 +123,7 @@
122123
F51BC0A02BB717D1009587C1 /* Stickers.xcstickers */ = {isa = PBXFileReference; lastKnownFileType = folder.stickers; name = Stickers.xcstickers; path = "bearTracks-stickers StickerPackExtension/Stickers.xcstickers"; sourceTree = "<group>"; };
123124
F51BC0B82BB71AF5009587C1 /* bearTracks Stickers.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "bearTracks Stickers.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
124125
F532B0322D4BE6D900B7C127 /* RegionalPoints.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegionalPoints.swift; sourceTree = "<group>"; };
126+
F5346CAA2D710D3400EBAC99 /* NotificationDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationDelegate.swift; sourceTree = "<group>"; };
125127
F53F363B2BB74B09008F196B /* bearTracks TV.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "bearTracks TV.app"; sourceTree = BUILT_PRODUCTS_DIR; };
126128
F53F36412BB74B0A008F196B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
127129
F53F36442BB74B0A008F196B /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
@@ -237,6 +239,7 @@
237239
F5D3D3452B5A17AE00A88A00 /* Info.plist */,
238240
F5081BA12B741D15001497DB /* AppState.swift */,
239241
F54E76C12B527D96003C65A2 /* bearTracksApp.swift */,
242+
F5346CAA2D710D3400EBAC99 /* NotificationDelegate.swift */,
240243
F5AE2E452B527E050033DB0D /* DataView.swift */,
241244
F5AE2E402B527E050033DB0D /* DetailedView.swift */,
242245
F5AE2E5D2B52FF3F0033DB0D /* LoginView.swift */,
@@ -489,6 +492,7 @@
489492
F59F8F7D2B7D2AD600D35A56 /* TeamStatController.swift in Sources */,
490493
F597AFFE2D6E74E0006CF1A5 /* CarouselView.swift in Sources */,
491494
F5081BA22B741D15001497DB /* AppState.swift in Sources */,
495+
F5346CAC2D710D3400EBAC99 /* NotificationDelegate.swift in Sources */,
492496
F540A13D2B549D2500611384 /* TeamView.swift in Sources */,
493497
F5AE2E4C2B527E050033DB0D /* DataView.swift in Sources */,
494498
F542E34C2B9C028F002F6E05 /* MatchDetailView.swift in Sources */,
@@ -549,14 +553,14 @@
549553
ASSETCATALOG_COMPILER_APPICON_NAME = "iMessage App Icon";
550554
CLANG_ENABLE_MODULES = YES;
551555
CODE_SIGN_STYLE = Automatic;
552-
CURRENT_PROJECT_VERSION = 101;
556+
CURRENT_PROJECT_VERSION = 103;
553557
DEVELOPMENT_TEAM = D6MFYYVHA8;
554558
GENERATE_INFOPLIST_FILE = YES;
555559
INFOPLIST_FILE = "sitckers StickerPackExtension/Info.plist";
556560
INFOPLIST_KEY_CFBundleDisplayName = bearTracks;
557561
INFOPLIST_KEY_NSStickerSharingLevel = OS;
558562
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
559-
MARKETING_VERSION = 6.0.1;
563+
MARKETING_VERSION = 6.0.2;
560564
PRODUCT_BUNDLE_IDENTIFIER = com.jayagra.beartracks.stickers;
561565
PRODUCT_NAME = "$(TARGET_NAME)";
562566
SKIP_INSTALL = YES;
@@ -573,14 +577,14 @@
573577
ASSETCATALOG_COMPILER_APPICON_NAME = "iMessage App Icon";
574578
CLANG_ENABLE_MODULES = YES;
575579
CODE_SIGN_STYLE = Automatic;
576-
CURRENT_PROJECT_VERSION = 101;
580+
CURRENT_PROJECT_VERSION = 103;
577581
DEVELOPMENT_TEAM = D6MFYYVHA8;
578582
GENERATE_INFOPLIST_FILE = YES;
579583
INFOPLIST_FILE = "sitckers StickerPackExtension/Info.plist";
580584
INFOPLIST_KEY_CFBundleDisplayName = bearTracks;
581585
INFOPLIST_KEY_NSStickerSharingLevel = OS;
582586
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
583-
MARKETING_VERSION = 6.0.1;
587+
MARKETING_VERSION = 6.0.2;
584588
PRODUCT_BUNDLE_IDENTIFIER = com.jayagra.beartracks.stickers;
585589
PRODUCT_NAME = "$(TARGET_NAME)";
586590
SKIP_INSTALL = YES;
@@ -596,7 +600,7 @@
596600
ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
597601
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
598602
CODE_SIGN_STYLE = Automatic;
599-
CURRENT_PROJECT_VERSION = 101;
603+
CURRENT_PROJECT_VERSION = 103;
600604
DEVELOPMENT_ASSET_PATHS = "\"beartracks-matches/Preview Content\"";
601605
DEVELOPMENT_TEAM = D6MFYYVHA8;
602606
ENABLE_PREVIEWS = YES;
@@ -609,7 +613,7 @@
609613
"$(inherited)",
610614
"@executable_path/Frameworks",
611615
);
612-
MARKETING_VERSION = 6.0.1;
616+
MARKETING_VERSION = 6.0.2;
613617
PRODUCT_BUNDLE_IDENTIFIER = com.jayagra.beartracks;
614618
PRODUCT_NAME = "$(TARGET_NAME)";
615619
SDKROOT = appletvos;
@@ -626,7 +630,7 @@
626630
ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
627631
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
628632
CODE_SIGN_STYLE = Automatic;
629-
CURRENT_PROJECT_VERSION = 101;
633+
CURRENT_PROJECT_VERSION = 103;
630634
DEVELOPMENT_ASSET_PATHS = "\"beartracks-matches/Preview Content\"";
631635
DEVELOPMENT_TEAM = D6MFYYVHA8;
632636
ENABLE_PREVIEWS = YES;
@@ -639,7 +643,7 @@
639643
"$(inherited)",
640644
"@executable_path/Frameworks",
641645
);
642-
MARKETING_VERSION = 6.0.1;
646+
MARKETING_VERSION = 6.0.2;
643647
PRODUCT_BUNDLE_IDENTIFIER = com.jayagra.beartracks;
644648
PRODUCT_NAME = "$(TARGET_NAME)";
645649
SDKROOT = appletvos;
@@ -777,7 +781,7 @@
777781
CODE_SIGN_ENTITLEMENTS = bearTracks/bearTracks.entitlements;
778782
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
779783
CODE_SIGN_STYLE = Automatic;
780-
CURRENT_PROJECT_VERSION = 101;
784+
CURRENT_PROJECT_VERSION = 103;
781785
DEVELOPMENT_ASSET_PATHS = "\"bearTracks/Preview Content\"";
782786
DEVELOPMENT_TEAM = D6MFYYVHA8;
783787
ENABLE_PREVIEWS = YES;
@@ -798,7 +802,7 @@
798802
"$(inherited)",
799803
"@executable_path/Frameworks",
800804
);
801-
MARKETING_VERSION = 6.0.1;
805+
MARKETING_VERSION = 6.0.2;
802806
PRODUCT_BUNDLE_IDENTIFIER = com.jayagra.beartracks;
803807
PRODUCT_NAME = "$(TARGET_NAME)";
804808
SDKROOT = xros;
@@ -810,6 +814,7 @@
810814
SWIFT_VERSION = 5.0;
811815
TARGETED_DEVICE_FAMILY = "1,2,6,7";
812816
TVOS_DEPLOYMENT_TARGET = 17.0;
817+
XROS_DEPLOYMENT_TARGET = 2.0;
813818
};
814819
name = Debug;
815820
};
@@ -821,7 +826,7 @@
821826
CODE_SIGN_ENTITLEMENTS = bearTracks/bearTracks.entitlements;
822827
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
823828
CODE_SIGN_STYLE = Automatic;
824-
CURRENT_PROJECT_VERSION = 101;
829+
CURRENT_PROJECT_VERSION = 103;
825830
DEVELOPMENT_ASSET_PATHS = "\"bearTracks/Preview Content\"";
826831
DEVELOPMENT_TEAM = D6MFYYVHA8;
827832
ENABLE_PREVIEWS = YES;
@@ -842,7 +847,7 @@
842847
"$(inherited)",
843848
"@executable_path/Frameworks",
844849
);
845-
MARKETING_VERSION = 6.0.1;
850+
MARKETING_VERSION = 6.0.2;
846851
PRODUCT_BUNDLE_IDENTIFIER = com.jayagra.beartracks;
847852
PRODUCT_NAME = "$(TARGET_NAME)";
848853
SDKROOT = xros;
@@ -854,6 +859,7 @@
854859
SWIFT_VERSION = 5.0;
855860
TARGETED_DEVICE_FAMILY = "1,2,6,7";
856861
TVOS_DEPLOYMENT_TARGET = 17.0;
862+
XROS_DEPLOYMENT_TARGET = 2.0;
857863
};
858864
name = Release;
859865
};
@@ -864,7 +870,7 @@
864870
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
865871
CODE_SIGN_ENTITLEMENTS = "beartracks-watch Watch App/beartracks-watch Watch App.entitlements";
866872
CODE_SIGN_STYLE = Automatic;
867-
CURRENT_PROJECT_VERSION = 101;
873+
CURRENT_PROJECT_VERSION = 103;
868874
DEVELOPMENT_ASSET_PATHS = "\"beartracks-watch Watch App/Preview Content\"";
869875
DEVELOPMENT_TEAM = D6MFYYVHA8;
870876
ENABLE_PREVIEWS = YES;
@@ -877,7 +883,7 @@
877883
"$(inherited)",
878884
"@executable_path/Frameworks",
879885
);
880-
MARKETING_VERSION = 6.0.1;
886+
MARKETING_VERSION = 6.0.2;
881887
PRODUCT_BUNDLE_IDENTIFIER = com.jayagra.beartracks.watchkitapp;
882888
PRODUCT_NAME = "$(TARGET_NAME)";
883889
SDKROOT = watchos;
@@ -896,7 +902,7 @@
896902
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
897903
CODE_SIGN_ENTITLEMENTS = "beartracks-watch Watch App/beartracks-watch Watch App.entitlements";
898904
CODE_SIGN_STYLE = Automatic;
899-
CURRENT_PROJECT_VERSION = 101;
905+
CURRENT_PROJECT_VERSION = 103;
900906
DEVELOPMENT_ASSET_PATHS = "\"beartracks-watch Watch App/Preview Content\"";
901907
DEVELOPMENT_TEAM = D6MFYYVHA8;
902908
ENABLE_PREVIEWS = YES;
@@ -909,7 +915,7 @@
909915
"$(inherited)",
910916
"@executable_path/Frameworks",
911917
);
912-
MARKETING_VERSION = 6.0.1;
918+
MARKETING_VERSION = 6.0.2;
913919
PRODUCT_BUNDLE_IDENTIFIER = com.jayagra.beartracks.watchkitapp;
914920
PRODUCT_NAME = "$(TARGET_NAME)";
915921
SDKROOT = watchos;

ios/beartracks/bearTracks/AppState.swift

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,38 +62,36 @@ class AppState: ObservableObject {
6262
}
6363

6464
func fetchMatchJson() {
65-
self.matchJsonStatus = (false, true)
66-
guard let url = URL(string: "https://beartracks.io/api/v1/events/matches/\(UserDefaults(suiteName: "group.com.jayagra.beartracks")?.string(forKey: "season") ?? "2025")/\(UserDefaults(suiteName: "group.com.jayagra.beartracks")?.string(forKey: "eventCode") ?? "TEST")/qualification/\(UserDefaults(suiteName: "group.com.jayagra.beartracks")?.string(forKey: "teamNumber") ?? "766")") else { return }
65+
self.matchJsonStatus = (false, false)
66+
guard let url = URL(string: "https://beartracks.io/api/v1/events/matches/\(UserDefaults().string(forKey: "season") ?? "2025")/\(UserDefaults().string(forKey: "eventCode") ?? "TEST")/qualification/\(UserDefaults().string(forKey: "teamNumber") ?? "766")") else { return }
6767

6868
sharedSession.dataTask(with: url) { data, _, error in
6969
if let data = data {
7070
do {
7171
let decoder = JSONDecoder()
7272
let result = try decoder.decode(MatchData.self, from: data)
73-
DispatchQueue.main.sync {
74-
DispatchQueue.main.async {
75-
self.matchJson = result.Schedule
76-
self.matchJsonStatus = (true, false)
77-
}
73+
DispatchQueue.main.async {
74+
self.matchJsonStatus = (true, false)
75+
self.matchJson = result.Schedule
7876
}
7977
} catch {
8078
print("parse error")
8179
DispatchQueue.main.async {
82-
self.matchJsonStatus = (false, true)
80+
self.matchJsonStatus = (true, true)
8381
}
8482
}
8583
} else if let error = error {
8684
print("fetch error: \(error)")
8785
DispatchQueue.main.async {
88-
self.matchJsonStatus = (false, true)
86+
self.matchJsonStatus = (true, true)
8987
}
9088
}
9189
}
9290
.resume()
9391
}
9492

9593
func fetchDataJson(completionBlock: @escaping ([DataEntry]) -> Void) {
96-
guard let url = URL(string: "https://beartracks.io/api/v1/data/brief/event/\(UserDefaults(suiteName: "group.com.jayagra.beartracks")?.string(forKey: "season") ?? "2025")/\(UserDefaults(suiteName: "group.com.jayagra.beartracks")?.string(forKey: "eventCode") ?? "TEST")") else { return }
94+
guard let url = URL(string: "https://beartracks.io/api/v1/data/brief/event/\(UserDefaults().string(forKey: "season") ?? "2025")/\(UserDefaults().string(forKey: "eventCode") ?? "TEST")") else { return }
9795

9896
var request = URLRequest(url: url)
9997
request.httpMethod = "GET"
@@ -135,7 +133,7 @@ class AppState: ObservableObject {
135133
}
136134

137135
func fetchTeamsJson() {
138-
guard let url = URL(string: "https://beartracks.io/api/v1/data/teams/\(UserDefaults(suiteName: "group.com.jayagra.beartracks")?.string(forKey: "season") ?? "2025")/\(UserDefaults(suiteName: "group.com.jayagra.beartracks")?.string(forKey: "eventCode") ?? "TEST")") else { return }
136+
guard let url = URL(string: "https://beartracks.io/api/v1/data/teams/\(UserDefaults().string(forKey: "season") ?? "2025")/\(UserDefaults().string(forKey: "eventCode") ?? "TEST")") else { return }
139137

140138
sharedSession.dataTask(with: url) { data, _, error in
141139
if let data = data {

ios/beartracks/bearTracks/DataView.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ struct DataView: View {
6666
}
6767
.navigationTitle("Data")
6868
} else {
69-
if self.loadFailed {
69+
if appState.dataJsonStatus.1 {
7070
VStack {
7171
Label("Failute", systemImage: "xmark.seal.fill")
7272
.padding(.bottom)
@@ -77,7 +77,7 @@ struct DataView: View {
7777
}
7878
.navigationTitle("Data")
7979
} else {
80-
if self.loadComplete {
80+
if appState.dataJsonStatus.0 {
8181
VStack {
8282
Label("None", systemImage: "questionmark.app.dashed")
8383
.padding(.bottom)

0 commit comments

Comments
 (0)