Skip to content

Commit

Permalink
Cached PMTiles for ASA Go (#4238)
Browse files Browse the repository at this point in the history
- Added filesystem permissions on iOS to app manifest
- Adds the capacitor filesystem package for reading and writing files to device disk
- Implements a custom openlayers `VectorTileSource` called `PMTilesFileVectorSource` that heavily borrows from the official `PMTilesVectorSource` that adds file specific tile loading.
- Implements a file cache that attempts to load stored copies of hfi, fire centre, fire zone and labels pmtiles falling back on an attempt to loading from object storage
  • Loading branch information
conbrad authored Feb 5, 2025
1 parent 4807bfe commit 88355d3
Show file tree
Hide file tree
Showing 17 changed files with 1,650 additions and 261 deletions.
2 changes: 1 addition & 1 deletion mobile/asa-go/capacitor.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
appId: 'io.ionic.starter',
appId: 'ca.bc.gov.asago',
appName: 'asa-go',
webDir: 'dist'
};
Expand Down
21 changes: 17 additions & 4 deletions mobile/asa-go/ios/App/App.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC3101FED79650016851F /* LaunchScreen.storyboard */; };
50B271D11FEDC1A000F3C39B /* public in Resources */ = {isa = PBXBuildFile; fileRef = 50B271D01FEDC1A000F3C39B /* public */; };
A084ECDBA7D38E1E42DFC39D /* Pods_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */; };
4309C9DBE16C4DF38D493C6C /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 1E60787A749448FB8E269E5A /* PrivacyInfo.xcprivacy */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand All @@ -30,6 +31,7 @@
AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App.framework; sourceTree = BUILT_PRODUCTS_DIR; };
AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = "<group>"; };
FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.debug.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.debug.xcconfig"; sourceTree = "<group>"; };
1E60787A749448FB8E269E5A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; name = "PrivacyInfo.xcprivacy"; path = "PrivacyInfo.xcprivacy"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -59,6 +61,7 @@
504EC3051FED79650016851F /* Products */,
7F8756D8B27F46E3366F6CEA /* Pods */,
27E2DDA53C4D2A4D1A88CE4A /* Frameworks */,
1E60787A749448FB8E269E5A /* Resources */,
);
sourceTree = "<group>";
};
Expand Down Expand Up @@ -94,6 +97,15 @@
name = Pods;
sourceTree = "<group>";
};
6ACB91DE59924FB1809508A1 /* Resources */ = {
isa = PBXGroup;
children = (
1E60787A749448FB8E269E5A /* PrivacyInfo.xcprivacy */,
);
name = Resources;
path = undefined;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -122,8 +134,8 @@
504EC2FC1FED79650016851F /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0920;
LastUpgradeCheck = 0920;
LastSwiftUpdateCheck = 920;
LastUpgradeCheck = 920;
TargetAttributes = {
504EC3031FED79650016851F = {
CreatedOnToolsVersion = 9.2;
Expand Down Expand Up @@ -163,6 +175,7 @@
50379B232058CBB4000EE86E /* capacitor.config.json in Resources */,
504EC30D1FED79650016851F /* Main.storyboard in Resources */,
2FAD9763203C412B000D30F8 /* config.xml in Resources */,
4309C9DBE16C4DF38D493C6C /* PrivacyInfo.xcprivacy in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -354,7 +367,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.0;
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
PRODUCT_BUNDLE_IDENTIFIER = io.ionic.starter;
PRODUCT_BUNDLE_IDENTIFIER = ca.bc.gov.asago;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_VERSION = 5.0;
Expand All @@ -373,7 +386,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = io.ionic.starter;
PRODUCT_BUNDLE_IDENTIFIER = ca.bc.gov.asago;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
SWIFT_VERSION = 5.0;
Expand Down
2 changes: 2 additions & 0 deletions mobile/asa-go/ios/App/App/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
<array>
<string>armv7</string>
</array>
<key>NSDocumentsFolderUsageDescription</key>
<string>Your app requires access to the Documents folder for file management.</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
Expand Down
1 change: 1 addition & 0 deletions mobile/asa-go/ios/App/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def capacitor_pods
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
pod 'CapacitorApp', :path => '../../node_modules/@capacitor/app'
pod 'CapacitorFilesystem', :path => '../../node_modules/@capacitor/filesystem'
pod 'CapacitorHaptics', :path => '../../node_modules/@capacitor/haptics'
pod 'CapacitorKeyboard', :path => '../../node_modules/@capacitor/keyboard'
pod 'CapacitorStatusBar', :path => '../../node_modules/@capacitor/status-bar'
Expand Down
8 changes: 7 additions & 1 deletion mobile/asa-go/ios/App/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ PODS:
- CapacitorApp (7.0.0):
- Capacitor
- CapacitorCordova (7.0.0)
- CapacitorFilesystem (7.0.0):
- Capacitor
- CapacitorHaptics (7.0.0):
- Capacitor
- CapacitorKeyboard (7.0.0):
Expand All @@ -15,6 +17,7 @@ DEPENDENCIES:
- "Capacitor (from `../../node_modules/@capacitor/ios`)"
- "CapacitorApp (from `../../node_modules/@capacitor/app`)"
- "CapacitorCordova (from `../../node_modules/@capacitor/ios`)"
- "CapacitorFilesystem (from `../../node_modules/@capacitor/filesystem`)"
- "CapacitorHaptics (from `../../node_modules/@capacitor/haptics`)"
- "CapacitorKeyboard (from `../../node_modules/@capacitor/keyboard`)"
- "CapacitorStatusBar (from `../../node_modules/@capacitor/status-bar`)"
Expand All @@ -26,6 +29,8 @@ EXTERNAL SOURCES:
:path: "../../node_modules/@capacitor/app"
CapacitorCordova:
:path: "../../node_modules/@capacitor/ios"
CapacitorFilesystem:
:path: "../../node_modules/@capacitor/filesystem"
CapacitorHaptics:
:path: "../../node_modules/@capacitor/haptics"
CapacitorKeyboard:
Expand All @@ -37,10 +42,11 @@ SPEC CHECKSUMS:
Capacitor: fcbee427ff437f414bbb3bc2d39364ad9bd2b8a5
CapacitorApp: 45cb7cbef4aa380b9236fd6980033eb5cde6fcd2
CapacitorCordova: 345f93b7edd121db98e4ec20ac94d6d7bcaf7e48
CapacitorFilesystem: 2881ad012b5c8d0ffbfed1216aadfc2cca16d5b5
CapacitorHaptics: 1fba3e460e7614349c6d5f868b1fccdc5c87b66d
CapacitorKeyboard: 2c26c6fccde35023c579fc37d4cae6326d5e6343
CapacitorStatusBar: 438e90beeeefa8276b24e6c5991cb02dd13e51bf

PODFILE CHECKSUM: f8c95c38f42283ff8d7c6bf6fa1435ecdce85ae9
PODFILE CHECKSUM: 57f6d064c0cf78e8c1949d60532f6d3d30cc6578

COCOAPODS: 1.16.2
21 changes: 21 additions & 0 deletions mobile/asa-go/ios/App/PrivacyInfo.xcprivacy
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?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>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C617.1</string>
</array>
</dict>
</array>
<key>NSPrivacyCollectedDataTypes</key>
<array/>
</dict>
</plist>
12 changes: 10 additions & 2 deletions mobile/asa-go/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"test": "vitest",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"@capacitor/android": "^7.0.0",
"@capacitor/android": "7.0.0",
"@capacitor/app": "7.0.0",
"@capacitor/core": "7.0.0",
"@capacitor/filesystem": "^7.0.0",
"@capacitor/haptics": "7.0.0",
"@capacitor/ios": "7.0.0",
"@capacitor/keyboard": "7.0.0",
Expand All @@ -27,21 +29,27 @@
"luxon": "^3.5.0",
"ol": "^10.3.1",
"ol-pmtiles": "^2.0.0",
"pmtiles": "^4.2.1",
"react": "^18.3.1",
"react-dom": "^18.3.1"
"react-dom": "^18.3.1",
"vitest": "^3.0.5"
},
"devDependencies": {
"@capacitor/cli": "7.0.0",
"@eslint/js": "^9.17.0",
"@types/jest": "^29.5.14",
"@types/lodash": "^4.17.14",
"@types/luxon": "^3.4.2",
"@types/react": "^18.3.18",
"@types/react-dom": "^18.3.5",
"@types/sinon": "^17.0.3",
"@vitejs/plugin-react-swc": "^3.5.0",
"eslint": "^9.17.0",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.16",
"globals": "^15.14.0",
"jsdom": "^26.0.0",
"sinon": "^19.0.2",
"typescript": "~5.6.2",
"typescript-eslint": "^8.18.2",
"vite": "^6.0.5"
Expand Down
22 changes: 4 additions & 18 deletions mobile/asa-go/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,18 @@
import { useState } from "react";
import { Box } from "@mui/material";

import { DateTime } from "luxon";
import FBAMap from "@/FBAMap";
import { FireCenter, FireShape, RunType } from "@/api/fbaAPI";
import { PST_UTC_OFFSET } from "@/utils/constants";
import { FireCenter, FireShape } from "@/api/fbaAPI";
import { AppHeader } from "@/AppHeader";
import { ASATabs } from "@/ASATabs";

const App = () => {
const [fireCenter] = useState<FireCenter | undefined>(undefined);

const [selectedFireShape, setSelectedFireShape] = useState<
FireShape | undefined
>(undefined);
const [zoomSource, setZoomSource] = useState<
"fireCenter" | "fireShape" | undefined
>("fireCenter");
const [dateOfInterest] = useState(
DateTime.now().setZone(`UTC${PST_UTC_OFFSET}`).hour < 13
? DateTime.now().setZone(`UTC${PST_UTC_OFFSET}`)
: DateTime.now().setZone(`UTC${PST_UTC_OFFSET}`).plus({ days: 1 })
const [selectedFireShape] = useState<FireShape | undefined>(undefined);
const [zoomSource] = useState<"fireCenter" | "fireShape" | undefined>(
"fireCenter"
);
const [runType] = useState(RunType.FORECAST);

return (
<Box
Expand All @@ -40,13 +30,9 @@ const App = () => {
<FBAMap
selectedFireCenter={fireCenter}
selectedFireShape={selectedFireShape}
forDate={dateOfInterest}
setSelectedFireShape={setSelectedFireShape}
fireShapeAreas={[]}
runType={runType}
zoomSource={zoomSource}
advisoryThreshold={0}
setZoomSource={setZoomSource}
/>
<ASATabs />
</Box>
Expand Down
Loading

0 comments on commit 88355d3

Please sign in to comment.