Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
84 changes: 84 additions & 0 deletions MOBILE_SETUP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Mobile Development Setup Guide

## Running the App on iOS and Android

The SafeDose app supports two mobile development workflows:

### Option 1: Using Expo Go (Recommended for Testing)

**Easiest setup for testing and development:**

1. Install Expo Go on your mobile device:
- [iOS App Store](https://apps.apple.com/app/expo-go/id982107779)
- [Google Play Store](https://play.google.com/store/apps/details?id=host.exp.exponent)

2. Start the development server:
```bash
npm run start:expo-go
```

3. Scan the QR code with:
- **iOS**: Camera app or Expo Go app
- **Android**: Expo Go app

4. The app will load directly on your device

### Option 2: Development Builds (Advanced)

**For production builds or custom native modules:**

1. **Prerequisites:**
- Android Studio (for Android)
- Xcode (for iOS)
- Physical device or emulator

2. **Android Setup:**
```bash
# Start Android emulator or connect device
npm run android
```

3. **iOS Setup:**
```bash
# Start iOS simulator or connect device
npm run ios
```

## Troubleshooting

### "App not loading on iOS and Android natively in terminal"

This typically means:

1. **No device/emulator connected**:
- For development builds: Set up Android Studio or Xcode
- For Expo Go: Use `npm run start:expo-go` instead

2. **expo-dev-client requires development build**:
- Use Expo Go workflow with `npm run start:expo-go`
- Or set up proper development environment

3. **Network issues**:
- Ensure your mobile device and computer are on the same WiFi network
- Try `expo start --tunnel` for remote testing

### Command Reference

```bash
# Web development
npm run web # Start web version

# Expo Go (recommended for most development)
npm run start:expo-go # Start for Expo Go app
npm run android:expo-go # Instructions for Android + Expo Go
npm run ios:expo-go # Instructions for iOS + Expo Go

# Development builds (advanced)
npm run start:dev-build # Start with dev client
npm run android # Build and run on Android
npm run ios # Build and run on iOS
```

## Dependencies Note

The app includes `expo-dev-client` for advanced features, but can run in Expo Go for most development tasks. If you only need basic functionality, you can remove `expo-dev-client` from package.json for a simpler setup.
80 changes: 44 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,43 +29,52 @@ To run the open-source version locally:

### 1. Clone the repo
```bash
git clone https://github.com/your-org/rodneyg-safedose.git
cd rodneyg-safedose

2. Install dependencies
git clone https://github.com/rodneyg/SafeDose.git
cd SafeDose
```

### 2. Install dependencies
```bash
npm install
```

3. iOS (Xcode required)

npx pod-install
npx expo run:ios

4. Android (Android Studio required)

npx expo run:android
### 3. Running the app

5. Web (experimental)

npx expo start --web
**Web (easiest setup):**
```bash
npm run web
```

Note: To use the AI-powered scan feature, you’ll need your own OpenAI API Key.
**Mobile (iOS/Android):**
For mobile development, see our detailed [Mobile Setup Guide](./MOBILE_SETUP.md) which covers:
- Using Expo Go (recommended for testing)
- Development builds (advanced)
- Troubleshooting common issues

Quick start for mobile testing:
```bash
# For Expo Go app testing
npm run start:expo-go

🔧 Environment Setup
# For development builds (requires Android Studio/Xcode)
npm run android # or npm run ios
```

Create a .env file in the root:
### 4. Environment Setup

Create a `.env` file in the root directory:
```bash
OPENAI_API_KEY=your-openai-key-here
```

Note: To use the AI-powered scan feature, you'll need your own OpenAI API Key.

---


📁 Directory Structure
## 📁 Directory Structure

rodneyg-safedose/
```
SafeDose/
├── app/ # Screens and navigation
├── hooks/ # Camera + system hooks
├── assets/ # Icons and images
Expand All @@ -77,31 +86,30 @@ rodneyg-safedose/
├── package.json # Dependencies
├── app.config.js # Expo app configuration
├── tsconfig.json # TypeScript settings
└── MOBILE_SETUP.md # Mobile development guide
```

---



🤝 Contributing
## 🤝 Contributing

We welcome contributions focused on safety, accessibility, and clarity.

Steps:
Fork the repo
Create a branch (git checkout -b your-feature)
Commit your changes
Submit a pull request
- Fork the repo
- Create a branch (`git checkout -b your-feature`)
- Commit your changes
- Submit a pull request

Please avoid introducing breaking changes or external dependencies unless necessary.

---

🛡 License
## 🛡 License

MIT License.
By using this project, you agree not to market it as a certified medical device without independent validation and regulatory approval.


Built by SafeLab — advancing open tools for human systems.
---

Built by SafeLab — advancing open tools for human systems.
41 changes: 41 additions & 0 deletions aspect-ratio-fix.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* CSS utilities to prevent aspect-ratio parsing errors in react-native-css-interop */

/* Override any problematic aspect-ratio values that might cause parsing errors */
.aspect-auto {
/* Convert 'auto' to a valid ratio to prevent parseDeclaration errors */
aspect-ratio: 1;
}

.aspect-square {
aspect-ratio: 1;
}

.aspect-video {
aspect-ratio: 16 / 9;
}

.aspect-content {
/* Replace with valid ratio */
aspect-ratio: 1;
}

/* Prevent empty or invalid aspect-ratio values */
[style*="aspect-ratio:"],
[style*="aspectRatio:"] {
/* Ensure minimum valid value */
min-height: 1px;
}

/* React Native specific fixes for aspect-ratio */
@media (react-native) {
.aspect-auto {
/* Use explicit width/height for RN instead of aspect-ratio */
width: 100%;
height: auto;
}

/* Disable aspect-ratio on React Native to prevent parsing issues */
* {
aspect-ratio: unset !important;
}
}
33 changes: 30 additions & 3 deletions contexts/AuthContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
const isSigningInAnonymouslyRef = useRef(false);
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
const fallbackTimeoutRef = useRef<NodeJS.Timeout | null>(null);
const initTimeoutRef = useRef<NodeJS.Timeout | null>(null);
const authInitializedRef = useRef(false);

const logout = async () => {
console.log('[AuthContext] ========== LOGOUT INITIATED ==========');
Expand Down Expand Up @@ -104,9 +106,9 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
} catch (error) {
console.error('[AuthContext] ❌ Error signing out:', error);
console.error('[AuthContext] Error details:', {
message: error?.message || 'Unknown error',
code: error?.code || 'No error code',
name: error?.name || 'Unknown error type'
message: (error as any)?.message || 'Unknown error',
code: (error as any)?.code || 'No error code',
name: (error as any)?.name || 'Unknown error type'
});
console.log('[AuthContext] Resetting isSigningOut to false due to error');
setIsSigningOut(false);
Expand All @@ -128,6 +130,17 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
}, [isSigningOut]);

useEffect(() => {
console.log('[AuthContext] Setting up authentication listener...');

// Set a timeout to ensure loading doesn't hang indefinitely on mobile
initTimeoutRef.current = setTimeout(() => {
if (!authInitializedRef.current) {
console.warn('[AuthContext] Auth initialization timeout - forcing loading to false');
setLoading(false);
authInitializedRef.current = true;
}
}, 10000); // 10 second timeout for mobile platforms

// Subscribe to auth state changes on the single `auth` instance
const unsubscribe = onAuthStateChanged(auth, (firebaseUser) => {
console.log('[AuthContext] ========== AUTH STATE CHANGED ==========');
Expand Down Expand Up @@ -248,6 +261,16 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
}
console.log('[AuthContext] Setting loading to false');
setLoading(false);

// Mark auth as initialized and clear timeout
if (!authInitializedRef.current) {
authInitializedRef.current = true;
if (initTimeoutRef.current) {
clearTimeout(initTimeoutRef.current);
initTimeoutRef.current = null;
}
}

console.log('[AuthContext] ========== AUTH STATE CHANGE COMPLETE ==========');
});

Expand All @@ -261,6 +284,10 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
clearTimeout(fallbackTimeoutRef.current);
fallbackTimeoutRef.current = null;
}
if (initTimeoutRef.current) {
clearTimeout(initTimeoutRef.current);
initTimeoutRef.current = null;
}
};
}, []); // Remove isSigningOut dependency to prevent auth listener recreation

Expand Down
3 changes: 3 additions & 0 deletions global.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
@tailwind components;
@tailwind utilities;

/* Import aspect-ratio fixes to prevent parsing errors */
@import url('./aspect-ratio-fix.css');

/* Define custom variables without overriding NativeWind defaults */
@layer base {
:root {
Expand Down
Loading