Files
mirror-os-flutter/apps/remote/lib/screens/connect_screen.dart
T
2026-07-11 21:51:34 -05:00

146 lines
4.7 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:mirror_ui/mirror_ui.dart';
import '../providers/connection_provider.dart';
class ConnectScreen extends ConsumerStatefulWidget {
const ConnectScreen({super.key});
@override
ConsumerState<ConnectScreen> createState() => _ConnectScreenState();
}
class _ConnectScreenState extends ConsumerState<ConnectScreen> {
final _hostController = TextEditingController();
bool _loaded = false;
@override
void initState() {
super.initState();
_loadSavedHost();
}
Future<void> _loadSavedHost() async {
final prefs = await SharedPreferences.getInstance();
final saved = prefs.getString('mirror_host') ?? 'mirror.local';
_hostController.text = saved;
setState(() => _loaded = true);
// Auto-connect only if not manually disconnected
final connection = ref.read(connectionProvider);
if (!connection.manualDisconnect && saved.isNotEmpty && saved != 'mirror.local') {
_connect();
}
}
Future<void> _saveHost(String host) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString('mirror_host', host);
}
@override
void dispose() {
_hostController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final connection = ref.watch(connectionProvider);
if (!_loaded) {
return const Scaffold(body: Center(child: CircularProgressIndicator()));
}
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Spacer(),
Icon(
Icons.cast_connected,
size: 64,
color: MirrorTheme.accent,
),
const SizedBox(height: 24),
Text(
'Mirror OS',
style: Theme.of(context).textTheme.headlineLarge,
textAlign: TextAlign.center,
),
const SizedBox(height: 8),
Text(
'Connect to your mirror',
style: Theme.of(context).textTheme.bodyMedium,
textAlign: TextAlign.center,
),
const SizedBox(height: 48),
TextField(
controller: _hostController,
decoration: InputDecoration(
labelText: 'Mirror address',
hintText: 'mirror.local or 192.168.x.x',
filled: true,
fillColor: MirrorTheme.surface,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide.none,
),
prefixIcon: const Icon(Icons.wifi),
),
keyboardType: TextInputType.url,
onSubmitted: (_) => _connect(),
),
const SizedBox(height: 16),
FilledButton(
onPressed: connection.connecting ? null : _connect,
style: FilledButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: connection.connecting
? const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Text('Connect'),
),
if (connection.error != null) ...[
const SizedBox(height: 16),
Text(
connection.error!,
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: MirrorTheme.danger,
),
textAlign: TextAlign.center,
),
],
const Spacer(),
Text(
'Make sure your phone is on the same\nWiFi network as the mirror',
style: Theme.of(context).textTheme.bodySmall,
textAlign: TextAlign.center,
),
],
),
),
),
);
}
void _connect() {
final host = _hostController.text.trim();
if (host.isNotEmpty) {
_saveHost(host);
ref.read(connectionProvider.notifier).connect(host);
}
}
}