Files
SigHej/Docs/APP.md

130 lines
4.3 KiB
Markdown
Raw Normal View History

2026-05-12 18:21:25 +02:00
# Mobile App — Social Proximity
## Technology Choice: Flutter
We chose **Flutter** over React Native for this project because BLE scanning requires close hardware access. Flutter compiles to native ARM code and communicates with the platform via direct platform channels — no JavaScript bridge between the app logic and the BLE hardware.
| | Flutter (chosen) | React Native |
|---|---|---|
| Language | Dart | TypeScript |
| BLE access | Platform channels — native | Via JS bridge |
| Performance | Compiles to native | JS runtime overhead |
| BLE library | `flutter_blue_plus` | `react-native-ble-plx` |
| Platforms | Android + iOS from one codebase | Same |
**Dart** is straightforward to learn if you know TypeScript: strongly typed, OOP, async/await, null safety built in.
## BLE Library: `flutter_blue_plus`
`flutter_blue_plus` is the most actively maintained Flutter BLE library. It supports:
- Scanning for nearby BLE peripherals
- Advertising as a BLE peripheral (Android 5+, iOS limited)
- Reading/writing GATT characteristics
- Connection state management
**Required permissions:**
_Android (`AndroidManifest.xml`):_
```xml
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
```
_iOS (`Info.plist`):_
```xml
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Used to detect nearby people with shared interests.</string>
```
## BLE Flow
```
App starts
└─► Check BLE permissions (request if missing)
└─► Generate ephemeral BLE token (UUID v4, per-session)
└─► Register token + interests with backend (POST /session)
User enables "Open to talk"
└─► Start BLE advertising (token in manufacturer data)
└─► Start BLE scanning for other tokens
└─► Open WebSocket to backend (/ws/{token})
Nearby token detected
└─► Send detected token to backend (POST /match)
└─► If match: WebSocket nudge received
└─► Display nudge card to user
User disables "Open to talk" or closes app
└─► Stop advertising + scanning
└─► Close WebSocket
└─► Session expires on backend (Redis TTL)
```
## Project Structure
```
app/
├── lib/
│ ├── main.dart
│ ├── screens/
│ │ ├── onboarding_screen.dart ← Interest selection on first launch
│ │ ├── home_screen.dart ← "Open to talk" toggle + nudge display
│ │ └── settings_screen.dart ← Manage interests, reset session
│ ├── widgets/
│ │ ├── nudge_card.dart ← The nudge notification UI
│ │ ├── interest_chip.dart ← Selectable interest tag
│ │ └── open_toggle.dart ← Big friendly on/off toggle
│ ├── services/
│ │ ├── ble_service.dart ← BLE scan/advertise logic
│ │ ├── api_service.dart ← HTTP client (register, match)
│ │ └── ws_service.dart ← WebSocket client (nudge receiver)
│ └── models/
│ ├── interest.dart
│ ├── session.dart
│ └── nudge.dart
├── android/
├── ios/
└── pubspec.yaml
```
## Screens
### Onboarding (first launch)
- Choose interest categories (multi-select chips)
- Brief explanation of how the app works
- Consent acknowledgement
### Home
- Large "Open to talk" toggle — the primary interaction
- When active: scanning indicator
- Nudge card appears when a match is found
- Shows shared interests (no name, no face, no location)
- "Say hello" is just a reminder — no in-app chat
### Settings
- Manage interest categories
- Reset ephemeral identity
- Privacy information
## State Management
For MVP simplicity: use Flutter's built-in `Provider` or `Riverpod`.
Avoid complex state management (no BLoC in MVP).
## Running Locally
```bash
cd app
flutter pub get
flutter run # runs on connected device or emulator
flutter run -d android
flutter run -d ios
```
**Prerequisites:**
- Flutter SDK ≥ 3.x
- Android Studio (for Android emulator) or Xcode (for iOS simulator)
- Physical device recommended for BLE testing — emulators do not support BLE scanning