218 lines
7.2 KiB
Dart
218 lines
7.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_svg/flutter_svg.dart';
|
|
import 'package:livekit_client/livekit_client.dart';
|
|
import 'package:livekit_example/widgets/text_field.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
import '../exts.dart';
|
|
import 'room.dart';
|
|
|
|
class ConnectPage extends StatefulWidget {
|
|
//
|
|
const ConnectPage({
|
|
Key? key,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
State<StatefulWidget> createState() => _ConnectPageState();
|
|
}
|
|
|
|
class _ConnectPageState extends State<ConnectPage> {
|
|
//
|
|
static const _storeKeyUri = 'uri';
|
|
static const _storeKeyToken = 'token';
|
|
static const _storeKeySimulcast = 'simulcast';
|
|
|
|
final _uriCtrl = TextEditingController();
|
|
final _tokenCtrl = TextEditingController();
|
|
bool _simulcast = false;
|
|
bool _busy = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_readPrefs();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_uriCtrl.dispose();
|
|
_tokenCtrl.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
// Read saved URL and Token
|
|
Future<void> _readPrefs() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
_uriCtrl.text = prefs.getString(_storeKeyUri) ?? '';
|
|
_tokenCtrl.text = prefs.getString(_storeKeyToken) ?? '';
|
|
setState(() {
|
|
_simulcast = prefs.getBool(_storeKeySimulcast) ?? false;
|
|
});
|
|
}
|
|
|
|
// Save URL and Token
|
|
Future<void> _writePrefs() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setString(_storeKeyUri, _uriCtrl.text);
|
|
await prefs.setString(_storeKeyToken, _tokenCtrl.text);
|
|
await prefs.setBool(_storeKeySimulcast, _simulcast);
|
|
}
|
|
|
|
Future<void> _connect(BuildContext ctx) async {
|
|
//
|
|
try {
|
|
setState(() {
|
|
_busy = true;
|
|
});
|
|
|
|
// Save URL and Token for convenience
|
|
await _writePrefs();
|
|
|
|
print('Connecting with url: ${_uriCtrl.text}, '
|
|
'token: ${_tokenCtrl.text}...');
|
|
|
|
// Try to connect to a room
|
|
// This will throw an Exception if it fails for any reason.
|
|
final room = await LiveKitClient.connect(
|
|
_uriCtrl.text,
|
|
_tokenCtrl.text,
|
|
options: ConnectOptions(
|
|
defaultPublishOptions: TrackPublishOptions(
|
|
simulcast: _simulcast,
|
|
),
|
|
),
|
|
);
|
|
|
|
await Navigator.push<void>(
|
|
ctx,
|
|
MaterialPageRoute(builder: (_) => RoomPage(room)),
|
|
);
|
|
} catch (error) {
|
|
print('Could not connect $error');
|
|
await ctx.showErrorDialog(error);
|
|
} finally {
|
|
setState(() {
|
|
_busy = false;
|
|
});
|
|
}
|
|
}
|
|
|
|
void _setSimulcast(bool? value) async {
|
|
if (value == null || _simulcast == value) return;
|
|
setState(() {
|
|
_simulcast = value;
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) => Scaffold(
|
|
body: Container(
|
|
alignment: Alignment.center,
|
|
child: Container(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 20,
|
|
),
|
|
constraints: const BoxConstraints(maxWidth: 400),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.only(bottom: 70),
|
|
child: SvgPicture.asset(
|
|
'images/logo-dark.svg',
|
|
),
|
|
),
|
|
|
|
Padding(
|
|
padding: const EdgeInsets.only(bottom: 30),
|
|
child: LKTextField(
|
|
label: 'Server URL',
|
|
ctrl: _uriCtrl,
|
|
),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.only(bottom: 50),
|
|
child: LKTextField(
|
|
label: 'Token',
|
|
ctrl: _tokenCtrl,
|
|
),
|
|
),
|
|
Container(
|
|
alignment: Alignment.center,
|
|
child: ElevatedButton(
|
|
onPressed: _busy ? null : () => _connect(context),
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
if (_busy)
|
|
const Padding(
|
|
padding: EdgeInsets.only(right: 10),
|
|
child: SizedBox(
|
|
height: 15,
|
|
width: 15,
|
|
child: CircularProgressIndicator(
|
|
color: Colors.white,
|
|
strokeWidth: 2,
|
|
),
|
|
),
|
|
),
|
|
const Text('CONNECT'),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
|
|
// Container(
|
|
// padding: const EdgeInsets.symmetric(
|
|
// vertical: 20,
|
|
// horizontal: 20,
|
|
// ),
|
|
// decoration: BoxDecoration(
|
|
// color: Theme.of(context).cardColor,
|
|
// borderRadius: BorderRadius.circular(8),
|
|
// // border: Border.all(
|
|
// // color: Theme.of(context).colorScheme.secondary),
|
|
// ),
|
|
// constraints: const BoxConstraints(
|
|
// maxWidth: 320,
|
|
// ),
|
|
// child: Column(
|
|
// mainAxisSize: MainAxisSize.min,
|
|
// children: [
|
|
// TextField(
|
|
// enableSuggestions: false,
|
|
// autocorrect: false,
|
|
// controller: _uriCtrl,
|
|
// decoration: const InputDecoration(labelText: 'URL'),
|
|
// ),
|
|
// TextField(
|
|
// enableSuggestions: false,
|
|
// autocorrect: false,
|
|
// controller: _tokenCtrl,
|
|
// decoration: const InputDecoration(labelText: 'Token'),
|
|
// ),
|
|
// Padding(
|
|
// padding: const EdgeInsets.only(top: 20),
|
|
// child: CheckboxListTile(
|
|
// controlAffinity: ListTileControlAffinity.leading,
|
|
// onChanged: (value) => _setSimulcast(value),
|
|
// title: const Text('Use Simulcast'),
|
|
// value: _simulcast,
|
|
// ),
|
|
// ),
|
|
//
|
|
// ],
|
|
// ),
|
|
// ),
|
|
]
|
|
// .map((e) => Padding(
|
|
// padding: const EdgeInsets.only(bottom: 50), child: e))
|
|
// .toList(),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|