Add release-signing config plugin, README, memory of PWA parity
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
89
README.md
89
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 |
|
||||
| --- | --- |
|
||||
| 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 |
|
||||
|
||||
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.
|
||||
|
||||
## Development
|
||||
|
||||
```sh
|
||||
npm install
|
||||
npx expo start # scan the QR with Expo Go (iOS or Android)
|
||||
```
|
||||
|
||||
2. Start the app
|
||||
Log in with the same Basic-auth credentials as the website.
|
||||
|
||||
```bash
|
||||
npx expo start
|
||||
## Android release APK
|
||||
|
||||
Signing expects (auto-skipped if absent, falling back to the debug key):
|
||||
|
||||
- keystore `~/.android-keys/health-app-release.jks` (alias `health`), or `$HEALTH_KEYSTORE`
|
||||
- password in `~/.android-keys/health-app-release.password`, or `$KEYSTORE_PASSWORD`
|
||||
|
||||
The signing config is injected by `plugins/with-release-signing.js` at prebuild.
|
||||
|
||||
```sh
|
||||
npx expo prebuild --platform android
|
||||
cd android && ./gradlew assembleRelease
|
||||
# → android/app/build/outputs/apk/release/app-release.apk
|
||||
```
|
||||
|
||||
In the output, you'll find options to open the app in a
|
||||
Install on GrapheneOS by copying the APK over (or via Obtainium once a
|
||||
Gitea release exists).
|
||||
|
||||
- [development build](https://docs.expo.dev/develop/development-builds/introduction/)
|
||||
- [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
|
||||
## iOS
|
||||
|
||||
You can start developing by editing the files inside the **app** directory. This project uses [file-based routing](https://docs.expo.dev/router/introduction).
|
||||
No Mac is available in this setup, so there is no local iOS build. Options:
|
||||
|
||||
## Get a fresh project
|
||||
- **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.
|
||||
|
||||
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.
|
||||
|
||||
### Other setup steps
|
||||
|
||||
- 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/)
|
||||
- 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
|
||||
|
||||
To learn more about developing your project with Expo, look at the following resources:
|
||||
|
||||
- [Expo documentation](https://docs.expo.dev/): Learn fundamentals, or go into advanced topics with our [guides](https://docs.expo.dev/guides).
|
||||
- [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.
|
||||
|
||||
## Join the community
|
||||
|
||||
Join our community of developers creating universal apps.
|
||||
|
||||
- [Expo on GitHub](https://github.com/expo/expo): View our open source platform and contribute.
|
||||
- [Discord community](https://chat.expo.dev): Chat with Expo users and ask questions.
|
||||
The `ios.bundleIdentifier` is already set to `xyz.rehbock.health`.
|
||||
|
||||
1
app.json
1
app.json
@@ -30,6 +30,7 @@
|
||||
"plugins": [
|
||||
"expo-router",
|
||||
"expo-secure-store",
|
||||
"./plugins/with-release-signing.js",
|
||||
[
|
||||
"expo-splash-screen",
|
||||
{
|
||||
|
||||
@@ -36,8 +36,8 @@
|
||||
"scripts": {
|
||||
"start": "expo start",
|
||||
"reset-project": "node ./scripts/reset-project.js",
|
||||
"android": "expo start --android",
|
||||
"ios": "expo start --ios",
|
||||
"android": "expo run:android",
|
||||
"ios": "expo run:ios",
|
||||
"web": "expo start --web",
|
||||
"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