Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
672ca48
Fix sleep tracking reliability with HealthKit sync
pH-7 Jul 16, 2026
2117354
Make iOS releases compatible with Xcode 26
pH-7 Jul 16, 2026
88c15d5
Bump iOS version for App Store submission
pH-7 Jul 16, 2026
f541488
Improve sleep estimates with reviewable on-device evidence
pH-7 Jul 18, 2026
c2ed87f
Add a battery-conscious Apple Watch sleep companion
pH-7 Jul 18, 2026
5ce5d12
Require committed sources for reproducible EAS releases
pH-7 Jul 18, 2026
b5354e6
Remove stale local build numbering under EAS versioning
pH-7 Jul 18, 2026
6182516
Include the npm lockfile in reproducible EAS builds
pH-7 Jul 18, 2026
f7d1eb1
Showcase Watch sleep insights with App Store artwork
pH-7 Jul 18, 2026
ad85217
Credit the app creator across product surfaces
pH-7 Jul 18, 2026
eb0d3f7
Stabilize Xcode build settings discovery
pH-7 Jul 18, 2026
a64d65a
Pin the verified iOS signing identity
pH-7 Jul 18, 2026
9e0ef90
Declare Watch HealthKit update purpose
pH-7 Jul 18, 2026
2f8955b
Harden sleep estimates against lifecycle failures
pH-7 Aug 13, 2026
fe25d13
Align sleep feedback with confirmed data
pH-7 Aug 13, 2026
c5f3c43
Respect system appearance without remounting views
pH-7 Aug 13, 2026
1009570
Remove misleading release configuration
pH-7 Aug 13, 2026
af86f97
Patch Expo 55 release dependencies
pH-7 Aug 13, 2026
2ee6c4d
Replace inaccurate App Store release materials
pH-7 Aug 13, 2026
2a252a6
Replace stale iPhone screenshots to improve conversion
pH-7 Aug 17, 2026
6ddddfe
Correct development guidance to match the released app
pH-7 Sep 5, 2026
c459119
Add lifecycle diagnostics without misleading background claims
pH-7 Sep 5, 2026
424e0c4
Add signing guidance to avoid unnecessary credential resets
pH-7 Sep 5, 2026
e5dce82
Ignore local release credentials to prevent disclosure
pH-7 Sep 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

# dependencies
node_modules/
package-lock.json
yarn.lock

# Expo
.expo/
Expand All @@ -12,13 +10,19 @@ web-build/
expo-env.d.ts

# Native
/ios/
/android/
*.orig.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision

# Local signing and store service-account credentials
credentials.json
pc-api-key.json

# Metro
.metro-health-check*

Expand Down
39 changes: 2 additions & 37 deletions App.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import React, { useEffect } from 'react';
import React from 'react';
import { StatusBar } from 'expo-status-bar';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { AppState, AppStateStatus } from 'react-native';
import { SleepProvider } from './src/context/SleepContext';
import { ThemeProvider, useTheme } from './src/context/ThemeContext';
import AppNavigator from './src/navigation/AppNavigator';
import BackgroundActivityService from './src/services/BackgroundActivityService';
import ErrorBoundary from './src/components/ErrorBoundary';

const AppContent = () => {
Expand All @@ -19,39 +17,6 @@ const AppContent = () => {
};

export default function App() {
useEffect(() => {
// Handle app state changes to prevent crashes on force close
const handleAppStateChange = async (nextAppState: AppStateStatus) => {
console.log(`🔄 App state changed to: ${nextAppState}`);

if (nextAppState === 'background' || nextAppState === 'inactive') {
try {
// Gracefully handle app going to background
console.log('📱 App going to background - preparing cleanup');
} catch (error) {
console.error('❌ Error handling app background state:', error);
}
}
};

// Subscribe to app state changes
const subscription = AppState.addEventListener('change', handleAppStateChange);

// Cleanup function to prevent memory leaks
return () => {
console.log('🧹 Cleaning up app state subscription');
subscription?.remove();

// Emergency cleanup for background service
try {
const backgroundService = BackgroundActivityService.getInstance();
backgroundService.stopMonitoring().catch(console.error);
} catch (error) {
console.error('❌ Emergency cleanup error:', error);
}
};
}, []);

return (
<ErrorBoundary>
<SafeAreaProvider>
Expand All @@ -63,4 +28,4 @@ export default function App() {
</SafeAreaProvider>
</ErrorBoundary>
);
}
}
44 changes: 44 additions & 0 deletions LOCAL_BUILD_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Local iOS builds

Use Node.js 20.19.4 or newer, npm, CocoaPods, and Xcode with iOS/watchOS SDKs installed. The repository uses Expo SDK 55 and contains native HealthKit, WatchConnectivity, and Swift code, so Expo Go cannot run the complete app.

## Install and run

```sh
npm ci
npm run ios
```

For a connected iPhone:

```sh
npx expo run:ios --device
```

Select the intended device and use a signing team authorized for the configured identifiers. A simulator is useful for navigation and empty states; verify real Health data, permissions, Watch communication, and battery behavior on physical devices.

The generated `ios/` and `android/` directories are ignored. Persistent native changes belong in `app.json`, config plugins, `modules/sleep-intelligence/`, or `targets/watch/`. Preserve local native edits before running `npm run prebuild:ios`: that command uses `--clean` and regenerates the iOS project.

## Release compilation without distribution signing

After generating the native workspace, a simulator Release build can check the iPhone and embedded Watch target:

```sh
xcodebuild -workspace ios/SleepDetector.xcworkspace \
-scheme SleepDetector -configuration Release \
-destination 'generic/platform=iOS Simulator' \
-derivedDataPath /tmp/detect-sleep-release-check \
CODE_SIGNING_ALLOWED=NO build
```

This is a compilation check, not an installable App Store archive. Follow the production EAS commands in the README to produce a distribution build. Check Apple's [current SDK requirements](https://developer.apple.com/news/upcoming-requirements/) before uploading.

## Signing and Keychain troubleshooting

- Check `ios.appleTeamId` and the bundle identifier in `app.json`. The `.env.example` variable does not override the current static configuration.
- Check `credentialsSource` in the production profile of `eas.json`. It currently uses credentials managed remotely by EAS.
- Run `bash ios-signing-help.sh` for diagnostic steps. The helper only prints guidance; it does not change credentials.
- A Keychain prompt asks for the password of the named keychain. This can differ from the current macOS login password, for example after a password change. Inspect the named keychain in Keychain Access; do not repeatedly revoke valid distribution certificates to solve a local unlock problem.
- Keep API keys, certificates, provisioning profiles, passwords, and `credentials.json` outside Git. Never paste their contents into public build logs or issues.

For environment failures, record the command, Xcode version, Node version, and the first useful error. Rebuild after native dependency or config-plugin changes; restarting Metro alone does not update native code.
62 changes: 62 additions & 0 deletions PRIVACY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Sleep Detector Privacy Policy

**Effective date:** August 14, 2026

Sleep Detector ("the app") is provided by SimpliXio Pte. Ltd. This policy explains how the app handles information.

## Summary

Sleep Detector is private by design. It does not require an account and does not include advertising, analytics, cross-app tracking, or a developer-operated cloud service for sleep and wellness data. Sleep records and settings are stored on the device unless the user explicitly exports them or enables Apple Health sync.

## Information handled by the app

The app can store the following information locally:

- app activity timestamps used to estimate an inactivity interval;
- sleep estimates, confirmed sleep periods, confidence details, and edits;
- optional wellness check-ins, settings, and notification preferences; and
- optional Apple Health information described below.

This information is used only to provide the app's sleep-review, history, export, and wellness features.

## Apple Health and Apple Watch

Apple Health access is optional and requested only after the user enables Health integration. With permission, the app can read sleep stages and selected recovery signals, including heart rate variability, resting heart rate, respiratory rate, and wrist temperature, to provide private sleep context. When Health sync is enabled, the app writes only sleep periods the user has confirmed.

Health information is not used for advertising, sold, shared with data brokers, or transmitted to a developer-operated server. Apple Health permissions can be changed at any time in the Health or Settings app.

The Apple Watch companion reads permitted Apple Health information only when the user requests a refresh. It does not run a continuous workout or always-on sensor session.

## Notifications

If the user grants notification permission, the app can schedule local bedtime reminders and confirmed-sleep summaries. Notification preferences can be changed in the app or in iOS Settings.

## Export and sharing

JSON and CSV exports are created only when the user requests them. The user chooses where an exported file is shared. The selected destination's privacy policy applies after the file leaves the app.

## Data retention and deletion

Sleep Detector keeps app data on the device until the user clears it in the app or uninstalls the app. Information previously written to Apple Health is controlled through the Health app and is not removed automatically when Sleep Detector is uninstalled.

## Security

The app relies on iOS device protections and HealthKit authorization controls. No method of storage is completely risk-free, so users should keep their device and Apple ID secure.

## Children

Sleep Detector is a general wellness tool and is not directed to children under 13. The app does not knowingly collect children's personal information.

## Health disclaimer

Sleep Detector supports personal awareness and journaling. It is not a medical device and does not diagnose, treat, cure, or prevent any disease or sleep disorder. Users should consult a qualified healthcare professional for medical concerns.

## Changes

This policy may be updated when the app or legal requirements change. The effective date above identifies the latest revision.

## Contact

For privacy questions, contact [contact@simplixio.tech](mailto:contact@simplixio.tech).

Product creator: [Pierre-Henry Soria](https://pierrehenry.dev).
52 changes: 52 additions & 0 deletions TESTING_CHECKLIST.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Sleep Detector release checks

Record the source commit, version/build, OS versions, devices, and outcomes. These are checks to perform, not claims that a release has passed them.

## Automated checks

```sh
npm test -- --runInBand
npx tsc --noEmit
npm run lint -- --quiet
npx expo-doctor
npx expo export --platform ios
```

Review dependency advisories with `npm audit --omit=dev`. Establish which paths are exposed and which fixes are compatible; do not automatically accept major upgrades or downgrades.

## Lifecycle and sleep review

- [ ] Fresh install opens without requiring Health access or an account.
- [ ] Set the inactivity threshold to 5 minutes. Background the app for less than 5 minutes, then reopen; no estimate should appear.
- [ ] Background it for more than 5 minutes, then reopen; inspect any estimate and its original app-away interval. Longer intervals can be filtered by the sleep-evidence rules.
- [ ] Confirm a reviewed estimate; one completed period should appear in history with the expected times.
- [ ] Edit an estimate before confirming; the saved period should use the edited times.
- [ ] Dismiss an estimate; it should not become a saved sleep period.
- [ ] Repeat after force-quitting an already-backgrounded app and after a device restart.
- [ ] Test overnight sleep, a nap, rapid background/foreground transitions, and a time-zone change. Confirm elapsed durations and wake-up dates.
- [ ] Start and stop a manual sleep session and verify its completed duration.

App-away timing cannot establish device-wide inactivity or sleep. No periodic background log is expected while iOS suspends the app. Run the timing checks from the installed app rather than expecting Expo Go or a terminal log to prove them.

## Apple Health and Watch (physical devices)

- [ ] Enable Health integration and inspect the permission explanations. Test denial and partial grants as well as full authorization.
- [ ] Unconfirmed or dismissed estimates must not write Health sleep samples.
- [ ] Confirm with sync enabled; inspect the resulting sample in Health. Reopening or retrying should not duplicate the same record.
- [ ] Disable sync, confirm another period, and verify no new Health write occurs.
- [ ] Revoke permissions in Health/Settings; the app should remain usable and explain sync failures.
- [ ] Compare imported sleep stages with Health, including overlapping sources and awake gaps.
- [ ] Test the Watch with no samples, with sleep samples, and with optional recovery metrics missing.
- [ ] Refresh on Watch, reopen iPhone, and verify the expected evidence is available. Check a temporarily disconnected Watch too.

## UX, privacy, and release

- [ ] Review Today, history, details, statistics, settings, and export in light and dark appearance.
- [ ] Check small screens, larger text, and VoiceOver; declare only accessibility features that have been verified.
- [ ] Test local reminders with notification permission granted and denied.
- [ ] Clear app data and check the visible history. Previously synced Health data is managed separately in Apple Health.
- [ ] Export JSON and CSV; verify times, contents, and the selected sharing destination.
- [ ] Measure an overnight physical-device session for battery use; a simulator build or unit test does not establish energy consumption.
- [ ] Produce a native Release build and validate distribution signing, entitlements, the Watch companion, and version/build numbers.
- [ ] Verify privacy/support links, age rating, metadata, current screenshots, and reviewer instructions in App Store Connect.
- [ ] Confirm the selected uploaded build matches the reviewed source before submitting. Verify the resulting review or public-release status directly.
16 changes: 0 additions & 16 deletions android/.gitignore

This file was deleted.

Loading
Loading