Files
external-cam/lib/home_screen.dart
Kai Chappell 1660696d7f wireless camera app for Android
Stream a phone's camera to a tablet over WiFi/hotspot.
WebSocket transport with native YUV-to-JPEG encoding,
UDP auto-discovery, remote control (zoom, flash, camera switch,
rotate, mirror) from the viewer.
2026-03-06 18:14:27 +00:00

98 lines
2.7 KiB
Dart

import 'package:flutter/material.dart';
import 'package:external_cam/camera_screen.dart';
import 'package:external_cam/viewer_screen.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('External Cam')),
body: Center(
child: Padding(
padding: const EdgeInsets.all(32),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_ModeCard(
icon: Icons.camera_alt,
title: 'Camera',
subtitle: 'Stream this device\'s camera over USB',
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const CameraScreen()),
),
),
const SizedBox(height: 24),
_ModeCard(
icon: Icons.tv,
title: 'Viewer',
subtitle: 'View the camera stream from a connected device',
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const ViewerScreen()),
),
),
const SizedBox(height: 32),
Text(
'Connect both devices with USB-C, then enable\n'
'USB tethering on the camera device.',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodySmall,
),
],
),
),
),
);
}
}
class _ModeCard extends StatelessWidget {
const _ModeCard({
required this.icon,
required this.title,
required this.subtitle,
required this.onTap,
});
final IconData icon;
final String title;
final String subtitle;
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
return Card(
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(12),
child: Padding(
padding: const EdgeInsets.all(32),
child: Row(
children: [
Icon(icon, size: 48),
const SizedBox(width: 24),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: Theme.of(context).textTheme.headlineSmall,
),
Text(subtitle),
],
),
),
const Icon(Icons.chevron_right),
],
),
),
),
);
}
}