146 lines
4.7 KiB
Dart
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);
|
|
}
|
|
}
|
|
}
|