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 createState() => _ConnectPageState(); } class _ConnectPageState extends State { // 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 _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 _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 _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( 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(), ), ), ), ); }