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
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,14 @@ coverage

.cursor/rules/nx-rules.mdc
.github/instructions/nx.instructions.md

# Expo
.expo/
.expo-shared/
*.jks
*.p8
*.p12
*.key
*.mobileprovision
*.orig.*
web-build/
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@
- **Customizable Actions**: Execute various VS Code commands and tasks as part of your demo.
- **PowerPoint Integration**: Seamlessly move from slides to code using the
[PowerPoint integration](https://demotime.show/integrations/powerpoint/).
- **Remote Control**: Control your presentations remotely via PWA (web) or native mobile apps (iOS & Android) with haptic feedback support.

## Remote Control Apps

Demo Time includes companion apps for remote control of your presentations:

- **PWA (Progressive Web App)**: Located in `apps/pwa` - A web-based remote control that works on any device with a modern browser
- **Expo Mobile App**: Located in `apps/expo-mobile` - Native iOS and Android app with haptic feedback for navigation buttons, providing tactile confirmation when advancing through demo steps

Both apps connect to the Demo Time API server running in VS Code to control your presentation remotely. The mobile app offers enhanced user experience with haptic touch feedback that isn't available in web/PWA environments.

## Getting Started

Expand Down
41 changes: 41 additions & 0 deletions apps/expo-mobile/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files

# dependencies
node_modules/

# Expo
.expo/
dist/
web-build/
expo-env.d.ts

# Native
.kotlin/
*.orig.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision

# Metro
.metro-health-check*

# debug
npm-debug.*
yarn-debug.*
yarn-error.*

# macOS
.DS_Store
*.pem

# local env files
.env*.local

# typescript
*.tsbuildinfo

# generated native folders
/ios
/android
55 changes: 55 additions & 0 deletions apps/expo-mobile/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from 'react';
import { StatusBar } from 'expo-status-bar';
import { BringToFrontProvider } from './src/contexts/BringToFrontContext';
import { useApi } from './src/hooks';
import { ConnectionScreen } from './src/screens/ConnectionScreen';
import { DemoScreen } from './src/screens/DemoScreen';

export default function App() {
return (
<BringToFrontProvider>
<StatusBar style="light" />
<AppContent />
</BringToFrontProvider>
);
}

function AppContent() {
const {
connectionStatus,
apiData,
loading,
connect,
disconnect,
triggerNext,
triggerPrevious,
runById,
refreshData,
} = useApi();

if (!connectionStatus.connected) {
return (
<ConnectionScreen
connectionStatus={connectionStatus}
loading={loading}
onConnect={connect}
/>
);
}

if (!apiData) {
return null;
}

return (
<DemoScreen
apiData={apiData}
loading={loading}
onTriggerNext={triggerNext}
onTriggerPrevious={triggerPrevious}
onRunById={runById}
onRefresh={refreshData}
onDisconnect={disconnect}
/>
);
}
132 changes: 132 additions & 0 deletions apps/expo-mobile/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Demo Time Mobile App

A native mobile application for iOS and Android that provides remote control for Demo Time presentations with haptic feedback support.

## Features

- **Cross-Platform**: Runs on both iOS and Android devices
- **Haptic Feedback**: Enhanced user experience with tactile feedback on navigation buttons
- **Real-time Updates**: Automatic polling to keep demo state synchronized
- **Native Performance**: Built with Expo and React Native for smooth performance
- **Persistent Connection**: Remembers your server URL for quick reconnection

## Getting Started

### Prerequisites

- Node.js (v16 or later)
- npm or yarn
- Expo CLI (`npm install -g expo-cli`)
- For iOS: macOS with Xcode
- For Android: Android Studio with Android SDK

### Installation

```bash
# Install dependencies
cd apps/expo-mobile
npm install
```

### Running the App

#### Development Mode

Start the Expo development server:

```bash
npm start
```

Then:
- Scan the QR code with your phone using the Expo Go app
- Press `i` for iOS simulator (macOS only)
- Press `a` for Android emulator

#### Running on Device

For iOS:
```bash
npm run ios
```

For Android:
```bash
npm run android
```

### Building for Production

For production builds, you'll need to set up EAS (Expo Application Services):

```bash
# Install EAS CLI
npm install -g eas-cli

# Configure EAS
eas build:configure

# Build for Android
npm run build:android

# Build for iOS
npm run build:ios
```

## How It Works

The app connects to the Demo Time VS Code extension's API server to control your presentation remotely.

1. **Connection**: Enter the URL of your Demo Time API server (e.g., `http://192.168.1.100:3000`)
2. **Navigation**: Use the Previous/Next buttons to navigate through demo steps
3. **Haptic Feedback**: Feel tactile feedback when pressing navigation buttons
4. **Direct Selection**: Tap any demo step to jump directly to it

## Haptic Feedback

This app uses Expo's Haptics API to provide tactile feedback:

- **Medium Impact**: Triggered when pressing Next/Previous buttons
- **Light Impact**: Triggered when selecting a specific demo step

The haptic feedback enhances the user experience by providing physical confirmation of button presses, especially useful during presentations.

## API Connection

The app communicates with the Demo Time VS Code extension API:

- `GET /api/demos` - Fetch current demo state
- `GET /api/next` - Trigger next demo step
- `GET /api/previous` - Trigger previous demo step
- `GET /api/runById?id={stepId}` - Run a specific demo step

## Architecture

The app follows the same patterns as the PWA:

- **Hooks**: `useApi` for API communication
- **Context**: `BringToFrontContext` for shared state
- **Screens**: `ConnectionScreen` and `DemoScreen`
- **Types**: Shared TypeScript interfaces for API data

## Comparison with PWA

| Feature | PWA | Mobile App |
|---------|-----|------------|
| Platform | Web browsers | iOS & Android native |
| Haptic Feedback | ❌ Not available | ✅ Supported |
| Installation | Add to home screen | App stores |
| Performance | Good | Better (native) |
| Offline capability | Service workers | Native storage |

## Contributing

Contributions are welcome! Please ensure your changes:
- Follow the existing code style
- Work on both iOS and Android
- Include appropriate error handling
- Maintain haptic feedback functionality

## License

MIT License - see the root LICENSE file for details
33 changes: 33 additions & 0 deletions apps/expo-mobile/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"expo": {
"name": "Demo Time Remote",
"slug": "demo-time-remote",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"userInterfaceStyle": "dark",
"newArchEnabled": true,
"splash": {
"image": "./assets/splash-icon.png",
"resizeMode": "contain",
"backgroundColor": "#202736"
},
"ios": {
"supportsTablet": true,
"bundleIdentifier": "com.demotime.mobile"
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#202736"
},
"package": "com.demotime.mobile",
"edgeToEdgeEnabled": true,
"predictiveBackGestureEnabled": false
},
"web": {
"favicon": "./assets/favicon.png"
},
"plugins": []
}
}
Binary file added apps/expo-mobile/assets/adaptive-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/expo-mobile/assets/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/expo-mobile/assets/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/expo-mobile/assets/splash-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions apps/expo-mobile/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { registerRootComponent } from 'expo';

import App from './App';

// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
// It also ensures that whether you load the app in Expo Go or in a native build,
// the environment is set up appropriately
registerRootComponent(App);
32 changes: 32 additions & 0 deletions apps/expo-mobile/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "@demotime/expo-mobile",
"version": "1.0.0",
"main": "index.ts",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"build:android": "eas build --platform android",
"build:ios": "eas build --platform ios",
"lint": "eslint . --ext .ts,.tsx"
},
"dependencies": {
"@react-native-async-storage/async-storage": "^2.2.0",
"@react-navigation/native": "^7.1.19",
"@react-navigation/stack": "^7.6.2",
"expo": "~54.0.22",
"expo-haptics": "~15.0.7",
"expo-status-bar": "~3.0.8",
"react": "19.1.0",
"react-native": "0.81.5",
"react-native-gesture-handler": "~2.28.0",
"react-native-safe-area-context": "^5.6.2",
"react-native-screens": "^4.16.0"
},
"devDependencies": {
"@types/react": "~19.1.0",
"typescript": "~5.9.2"
},
"private": true
}
44 changes: 44 additions & 0 deletions apps/expo-mobile/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"name": "expo-mobile",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"sourceRoot": "apps/expo-mobile/src",
"targets": {
"start": {
"executor": "nx:run-commands",
"options": {
"command": "npx expo start",
"cwd": "apps/expo-mobile"
}
},
"android": {
"executor": "nx:run-commands",
"options": {
"command": "npx expo run:android",
"cwd": "apps/expo-mobile"
}
},
"ios": {
"executor": "nx:run-commands",
"options": {
"command": "npx expo run:ios",
"cwd": "apps/expo-mobile"
}
},
"build:android": {
"executor": "nx:run-commands",
"options": {
"command": "npx eas build --platform android",
"cwd": "apps/expo-mobile"
}
},
"build:ios": {
"executor": "nx:run-commands",
"options": {
"command": "npx eas build --platform ios",
"cwd": "apps/expo-mobile"
}
}
},
"tags": ["type:app", "scope:mobile"]
}
Loading