Add release-signing config plugin, README, memory of PWA parity
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
83
README.md
83
README.md
@@ -1,56 +1,61 @@
|
|||||||
# Welcome to your Expo app 👋
|
# health-app
|
||||||
|
|
||||||
This is an [Expo](https://expo.dev) project created with [`create-expo-app`](https://www.npmjs.com/package/create-expo-app).
|
Cross-platform (iOS + Android) Expo app — native front end for the private
|
||||||
|
health dashboard at **https://health.rehbock.xyz**.
|
||||||
|
|
||||||
## Get started
|
The app is a pure client: all data lives on the server and is fetched live over
|
||||||
|
HTTPS with HTTP Basic auth. Nothing is stored on the device except the auth
|
||||||
|
token (in the platform keychain via `expo-secure-store`).
|
||||||
|
|
||||||
1. Install dependencies
|
## Screens
|
||||||
|
|
||||||
```bash
|
| Screen | Data source |
|
||||||
npm install
|
| --- | --- |
|
||||||
```
|
| Today | overview cards + clinical priorities (`health-meta.json`) |
|
||||||
|
| Blood | `/api/health/v1/biomarkers` + `/draws` — search, flags, sparklines |
|
||||||
|
| Sleep | `/api/health/v1/sleep` + `sleep-data.json` — stacked stage chart |
|
||||||
|
| Train | `/api/health/v1/workouts` — weekly volume chart, expandable sessions |
|
||||||
|
| Body | `dexa-scans.json` — DXA summary with deltas, regions, indices |
|
||||||
|
| Mind | `/api/meditation/v1/stats` + `/sessions` |
|
||||||
|
| DNA | `ancestry-traits.json` — 99 AncestryDNA traits |
|
||||||
|
|
||||||
2. Start the app
|
Ported from the PWA at `health.rehbock.xyz/app/`
|
||||||
|
(repo `marcus/health.rehbock.xyz`, `app/index.html`); charts are
|
||||||
|
react-native-svg, tap a bar for the night/week detail.
|
||||||
|
|
||||||
```bash
|
## Development
|
||||||
npx expo start
|
|
||||||
```
|
|
||||||
|
|
||||||
In the output, you'll find options to open the app in a
|
```sh
|
||||||
|
npm install
|
||||||
- [development build](https://docs.expo.dev/develop/development-builds/introduction/)
|
npx expo start # scan the QR with Expo Go (iOS or Android)
|
||||||
- [Android emulator](https://docs.expo.dev/workflow/android-studio-emulator/)
|
|
||||||
- [iOS simulator](https://docs.expo.dev/workflow/ios-simulator/)
|
|
||||||
- [Expo Go](https://expo.dev/go), a limited sandbox for trying out app development with Expo
|
|
||||||
|
|
||||||
You can start developing by editing the files inside the **app** directory. This project uses [file-based routing](https://docs.expo.dev/router/introduction).
|
|
||||||
|
|
||||||
## Get a fresh project
|
|
||||||
|
|
||||||
When you're ready, run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run reset-project
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This command will move the starter code to the **app-example** directory and create a blank **app** directory where you can start developing.
|
Log in with the same Basic-auth credentials as the website.
|
||||||
|
|
||||||
### Other setup steps
|
## Android release APK
|
||||||
|
|
||||||
- To set up ESLint for linting, run `npx expo lint`, or follow our guide on ["Using ESLint and Prettier"](https://docs.expo.dev/guides/using-eslint/)
|
Signing expects (auto-skipped if absent, falling back to the debug key):
|
||||||
- If you'd like to set up unit testing, follow our guide on ["Unit Testing with Jest"](https://docs.expo.dev/develop/unit-testing/)
|
|
||||||
- Learn more about the TypeScript setup in this template in our guide on ["Using TypeScript"](https://docs.expo.dev/guides/typescript/)
|
|
||||||
|
|
||||||
## Learn more
|
- keystore `~/.android-keys/health-app-release.jks` (alias `health`), or `$HEALTH_KEYSTORE`
|
||||||
|
- password in `~/.android-keys/health-app-release.password`, or `$KEYSTORE_PASSWORD`
|
||||||
|
|
||||||
To learn more about developing your project with Expo, look at the following resources:
|
The signing config is injected by `plugins/with-release-signing.js` at prebuild.
|
||||||
|
|
||||||
- [Expo documentation](https://docs.expo.dev/): Learn fundamentals, or go into advanced topics with our [guides](https://docs.expo.dev/guides).
|
```sh
|
||||||
- [Learn Expo tutorial](https://docs.expo.dev/tutorial/introduction/): Follow a step-by-step tutorial where you'll create a project that runs on Android, iOS, and the web.
|
npx expo prebuild --platform android
|
||||||
|
cd android && ./gradlew assembleRelease
|
||||||
|
# → android/app/build/outputs/apk/release/app-release.apk
|
||||||
|
```
|
||||||
|
|
||||||
## Join the community
|
Install on GrapheneOS by copying the APK over (or via Obtainium once a
|
||||||
|
Gitea release exists).
|
||||||
|
|
||||||
Join our community of developers creating universal apps.
|
## iOS
|
||||||
|
|
||||||
- [Expo on GitHub](https://github.com/expo/expo): View our open source platform and contribute.
|
No Mac is available in this setup, so there is no local iOS build. Options:
|
||||||
- [Discord community](https://chat.expo.dev): Chat with Expo users and ask questions.
|
|
||||||
|
- **Expo Go** (zero setup): `npx expo start`, scan the QR from the iPhone.
|
||||||
|
- **EAS Build** (real install): `npx eas build -p ios` — needs an Apple
|
||||||
|
Developer account; produces a TestFlight/ad-hoc build in the cloud.
|
||||||
|
|
||||||
|
The `ios.bundleIdentifier` is already set to `xyz.rehbock.health`.
|
||||||
|
|||||||
1
app.json
1
app.json
@@ -30,6 +30,7 @@
|
|||||||
"plugins": [
|
"plugins": [
|
||||||
"expo-router",
|
"expo-router",
|
||||||
"expo-secure-store",
|
"expo-secure-store",
|
||||||
|
"./plugins/with-release-signing.js",
|
||||||
[
|
[
|
||||||
"expo-splash-screen",
|
"expo-splash-screen",
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -36,8 +36,8 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "expo start",
|
"start": "expo start",
|
||||||
"reset-project": "node ./scripts/reset-project.js",
|
"reset-project": "node ./scripts/reset-project.js",
|
||||||
"android": "expo start --android",
|
"android": "expo run:android",
|
||||||
"ios": "expo start --ios",
|
"ios": "expo run:ios",
|
||||||
"web": "expo start --web",
|
"web": "expo start --web",
|
||||||
"lint": "expo lint"
|
"lint": "expo lint"
|
||||||
},
|
},
|
||||||
|
|||||||
37
plugins/with-release-signing.js
Normal file
37
plugins/with-release-signing.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/* Injects a release signing config into the prebuilt android project.
|
||||||
|
Keystore: $HEALTH_KEYSTORE or ~/.android-keys/health-app-release.jks
|
||||||
|
Password: $KEYSTORE_PASSWORD or ~/.android-keys/health-app-release.password
|
||||||
|
Falls back to the debug keystore when neither exists. */
|
||||||
|
const { withAppBuildGradle } = require('expo/config-plugins');
|
||||||
|
|
||||||
|
const SIGNING = ` release {
|
||||||
|
// keystore lives outside the repo; password from env or ~/.android-keys
|
||||||
|
def ksPath = System.getenv("HEALTH_KEYSTORE") ?: "\${System.properties['user.home']}/.android-keys/health-app-release.jks"
|
||||||
|
def passFile = new File("\${System.properties['user.home']}/.android-keys/health-app-release.password")
|
||||||
|
def ksPass = System.getenv("KEYSTORE_PASSWORD") ?: (passFile.exists() ? passFile.text.trim() : null)
|
||||||
|
if (new File(ksPath).exists() && ksPass != null) {
|
||||||
|
storeFile file(ksPath)
|
||||||
|
storePassword ksPass
|
||||||
|
keyAlias System.getenv("KEY_ALIAS") ?: "health"
|
||||||
|
keyPassword ksPass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
|
||||||
|
module.exports = function withReleaseSigning(config) {
|
||||||
|
return withAppBuildGradle(config, (cfg) => {
|
||||||
|
let g = cfg.modResults.contents;
|
||||||
|
if (!g.includes('def ksPath')) {
|
||||||
|
g = g.replace(
|
||||||
|
/(signingConfigs \{[\s\S]*?keyPassword 'android'\n {8}\}\n)( {4}\})/,
|
||||||
|
`$1${SIGNING}`,
|
||||||
|
);
|
||||||
|
g = g.replace(
|
||||||
|
/\/\/ Caution![^\n]*\n\s*\/\/ see https:\/\/reactnative\.dev[^\n]*\n\s*signingConfig signingConfigs\.debug/,
|
||||||
|
'signingConfig signingConfigs.release.storeFile ? signingConfigs.release : signingConfigs.debug',
|
||||||
|
);
|
||||||
|
cfg.modResults.contents = g;
|
||||||
|
}
|
||||||
|
return cfg;
|
||||||
|
});
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user