@craft-native/ios 0.0.101 → 0.0.103
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -0
- package/package.json +1 -1
- package/templates/CraftApp.swift +20 -0
package/README.md
CHANGED
|
@@ -143,6 +143,34 @@ Edit `craft.config.json` in your iOS project:
|
|
|
143
143
|
}
|
|
144
144
|
```
|
|
145
145
|
|
|
146
|
+
The app name is shown as written (`"HQ.training"` is fine); the Xcode
|
|
147
|
+
project, target and Swift types use a PascalCase identifier made from it
|
|
148
|
+
(`HQTraining`). A key left out of the file keeps its default.
|
|
149
|
+
|
|
150
|
+
Appearance and navigation:
|
|
151
|
+
|
|
152
|
+
```json
|
|
153
|
+
{
|
|
154
|
+
"appearance": "system",
|
|
155
|
+
"backgroundColor": "#f8fafc",
|
|
156
|
+
"backgroundColorDark": "#020617",
|
|
157
|
+
"swipeNavigation": true
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
- `appearance`: `"system"` follows the phone's Light/Dark setting (and the
|
|
162
|
+
page's `prefers-color-scheme`), with a status bar that reads on either;
|
|
163
|
+
`"light"` and `"dark"` pin one. Without it, `darkMode` decides as before.
|
|
164
|
+
- `backgroundColorDark`: the launch screen and webview background in Dark Mode.
|
|
165
|
+
- `swipeNavigation`: an edge swipe goes back and forward through the page's
|
|
166
|
+
history, pushState entries included.
|
|
167
|
+
|
|
168
|
+
Debug builds let Safari's Develop menu inspect the webview, and relay the
|
|
169
|
+
page's console, uncaught errors, rejected promises and failed script loads to
|
|
170
|
+
the device log as `[craft page] …`, so a page that only breaks inside the app
|
|
171
|
+
can be read with `xcrun simctl spawn booted log show --predicate 'process ==
|
|
172
|
+
"YourApp"'`. Release builds do neither.
|
|
173
|
+
|
|
146
174
|
When push notifications are enabled, generated Debug builds use the APNs
|
|
147
175
|
development environment and Release builds use the production environment.
|
|
148
176
|
The generated entitlements select the correct value from the active Xcode
|
|
@@ -240,6 +268,15 @@ console.log(nfcData); // Tag content
|
|
|
240
268
|
await window.craft.requestHealthAuthorization(['stepCount', 'heartRate']);
|
|
241
269
|
const steps = await window.craft.getHealthData('stepCount', startDate, endDate);
|
|
242
270
|
|
|
271
|
+
// Through craft-native/mobile's `health` service:
|
|
272
|
+
import { health } from 'craft-native/mobile'
|
|
273
|
+
// Read only: the sheet asks for access, not "access and update".
|
|
274
|
+
await health.requestAuthorization(['workouts', 'heartRate', 'sleep'], { write: false })
|
|
275
|
+
// Apple Health workouts (the watch's and every app's), newest first.
|
|
276
|
+
const workouts = await health.getWorkouts({ startDate: Date.now() - 30 * 86400000 })
|
|
277
|
+
// One value per local day: sums, averages, the latest weight, hours asleep.
|
|
278
|
+
const hrv = await health.getDailyStatistics('heartRateVariability', { startDate: Date.now() - 30 * 86400000 })
|
|
279
|
+
|
|
243
280
|
// Screen Capture
|
|
244
281
|
const screenshotBase64 = await window.craft.takeScreenshot();
|
|
245
282
|
|
package/package.json
CHANGED
package/templates/CraftApp.swift
CHANGED
|
@@ -1703,12 +1703,32 @@ struct CraftWebView: UIViewRepresentable {
|
|
|
1703
1703
|
decisionHandler(.allow)
|
|
1704
1704
|
return
|
|
1705
1705
|
}
|
|
1706
|
+
// An iframe the app's page embeds loads in place. Only the main
|
|
1707
|
+
// frame's navigations leave for Safari: cancelling the frame's
|
|
1708
|
+
// too left every embed blank, a YouTube or Vimeo player among them.
|
|
1709
|
+
if let frame = navigationAction.targetFrame, !frame.isMainFrame, isEmbeddableFrameURL(url) {
|
|
1710
|
+
decisionHandler(.allow)
|
|
1711
|
+
return
|
|
1712
|
+
}
|
|
1706
1713
|
if navigationAction.targetFrame?.isMainFrame != false {
|
|
1707
1714
|
UIApplication.shared.open(url)
|
|
1708
1715
|
}
|
|
1709
1716
|
decisionHandler(.cancel)
|
|
1710
1717
|
}
|
|
1711
1718
|
|
|
1719
|
+
/// What an iframe inside the app's page may load: a video player, a
|
|
1720
|
+
/// payment form, a map. It stays inside its frame, and the bridge
|
|
1721
|
+
/// answers only `isTrustedOrigin`, so loading one reaches nothing
|
|
1722
|
+
/// native. Plain http is left to the trusted local origins.
|
|
1723
|
+
private func isEmbeddableFrameURL(_ url: URL) -> Bool {
|
|
1724
|
+
switch url.scheme?.lowercased() {
|
|
1725
|
+
case "https", "about", "data", "blob":
|
|
1726
|
+
return true
|
|
1727
|
+
default:
|
|
1728
|
+
return false
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1712
1732
|
func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
|
|
1713
1733
|
webView.reload()
|
|
1714
1734
|
}
|